From: dtucker Date: Fri, 8 Jan 2010 06:08:00 +0000 (+0000) Subject: - markus@cvs.openbsd.org 2009/11/11 21:37:03 X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/commitdiff_plain/7501ed0d668ada42afeeecf1b94aa2bd7a01088f?hp=fe5bc072372d65c280a9dbc4e74dbd83d4efcfaf - markus@cvs.openbsd.org 2009/11/11 21:37:03 [channels.c channels.h] fix race condition in x11/agent channel allocation: don't read after the end of the select read/write fdset and make sure a reused FD is not touched before the pre-handlers are called. with and ok djm@ --- diff --git a/ChangeLog b/ChangeLog index a2cee09d..96e338c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -51,6 +51,12 @@ [sshconnect2.c channels.c sshconnect.c] Set close-on-exec on various descriptors so they don't get leaked to child processes. bz #1643, patch from jchadima at redhat, ok deraadt. + - markus@cvs.openbsd.org 2009/11/11 21:37:03 + [channels.c channels.h] + fix race condition in x11/agent channel allocation: don't read after + the end of the select read/write fdset and make sure a reused FD + is not touched before the pre-handlers are called. + with and ok djm@ 20091226 - (tim) [contrib/cygwin/Makefile] Install ssh-copy-id and ssh-copy-id.1 diff --git a/channels.c b/channels.c index eb0c61d8..94939239 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.298 2009/11/10 04:30:44 dtucker Exp $ */ +/* $OpenBSD: channels.c,v 1.299 2009/11/11 21:37:03 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -331,6 +331,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, c->output_filter = NULL; c->filter_ctx = NULL; c->filter_cleanup = NULL; + c->delayed = 1; /* prevent call to channel_post handler */ TAILQ_INIT(&c->status_confirms); debug("channel %d: new [%s]", found, remote_name); return c; @@ -1228,7 +1229,6 @@ channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset) int ret; have = buffer_len(&c->input); - c->delayed = 0; debug2("channel %d: pre_dynamic: have %d", c->self, have); /* buffer_dump(&c->input); */ /* check if the fixed size part of the packet is in buffer. */ @@ -1432,16 +1432,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset) if (c->path != NULL) nc->path = xstrdup(c->path); - if (nextstate == SSH_CHANNEL_DYNAMIC) { - /* - * do not call the channel_post handler until - * this flag has been reset by a pre-handler. - * otherwise the FD_ISSET calls might overflow - */ - nc->delayed = 1; - } else { + if (nextstate != SSH_CHANNEL_DYNAMIC) port_open_helper(nc, rtype); - } } } @@ -1786,8 +1778,6 @@ channel_check_window(Channel *c) static void channel_post_open(Channel *c, fd_set *readset, fd_set *writeset) { - if (c->delayed) - return; channel_handle_rfd(c, readset, writeset); channel_handle_wfd(c, readset, writeset); if (!compat20) @@ -1919,17 +1909,23 @@ static void channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset) { static int did_init = 0; - u_int i; + u_int i, oalloc; Channel *c; if (!did_init) { channel_handler_init(); did_init = 1; } - for (i = 0; i < channels_alloc; i++) { + for (i = 0, oalloc = channels_alloc; i < oalloc; i++) { c = channels[i]; if (c == NULL) continue; + if (c->delayed) { + if (ftab == channel_pre) + c->delayed = 0; + else + continue; + } if (ftab[c->type] != NULL) (*ftab[c->type])(c, readset, writeset); channel_garbage_collect(c); diff --git a/channels.h b/channels.h index b0f5dc32..4dbeeb6e 100644 --- a/channels.h +++ b/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.99 2009/10/28 16:38:18 reyk Exp $ */ +/* $OpenBSD: channels.h,v 1.100 2009/11/11 21:37:03 markus Exp $ */ /* * Author: Tatu Ylonen @@ -97,7 +97,11 @@ struct Channel { int wfd_isatty; /* wfd is a tty */ int client_tty; /* (client) TTY has been requested */ int force_drain; /* force close on iEOF */ - int delayed; /* fdset hack */ + int delayed; /* post-select handlers for newly created + * channels are delayed until the first call + * to a matching pre-select handler. + * this way post-select handlers are not + * accidenly called if a FD gets reused */ Buffer input; /* data read from socket, to be sent over * encrypted connection */ Buffer output; /* data received over encrypted connection for