]> andersk Git - openssh.git/commitdiff
- markus@cvs.openbsd.org 2009/11/11 21:37:03
authordtucker <dtucker>
Fri, 8 Jan 2010 06:08:00 +0000 (06:08 +0000)
committerdtucker <dtucker>
Fri, 8 Jan 2010 06:08:00 +0000 (06:08 +0000)
     [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@

ChangeLog
channels.c
channels.h

index a2cee09d5cfb456cb16a52044374ad373abdbe8d..96e338c003535f2bb63deb64e6904e0c8ea093cd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
      [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
index eb0c61d8b3be969ee81e787c9aa03443f3cc4b4d..94939239022df3867337d554afc3d14a39c28af0 100644 (file)
@@ -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 <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, 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);
index b0f5dc3216ef36c55e12aadc08fa50f932a69949..4dbeeb6e158e43aca83cad5081aeaa3f6e98427b 100644 (file)
@@ -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 <ylo@cs.hut.fi>
@@ -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
This page took 0.056423 seconds and 5 git commands to generate.