diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | channels.c | 26 | ||||
-rw-r--r-- | channels.h | 8 |
3 files changed, 23 insertions, 17 deletions
@@ -51,6 +51,12 @@ | |||
51 | [sshconnect2.c channels.c sshconnect.c] | 51 | [sshconnect2.c channels.c sshconnect.c] |
52 | Set close-on-exec on various descriptors so they don't get leaked to | 52 | Set close-on-exec on various descriptors so they don't get leaked to |
53 | child processes. bz #1643, patch from jchadima at redhat, ok deraadt. | 53 | child processes. bz #1643, patch from jchadima at redhat, ok deraadt. |
54 | - markus@cvs.openbsd.org 2009/11/11 21:37:03 | ||
55 | [channels.c channels.h] | ||
56 | fix race condition in x11/agent channel allocation: don't read after | ||
57 | the end of the select read/write fdset and make sure a reused FD | ||
58 | is not touched before the pre-handlers are called. | ||
59 | with and ok djm@ | ||
54 | 60 | ||
55 | 20091226 | 61 | 20091226 |
56 | - (tim) [contrib/cygwin/Makefile] Install ssh-copy-id and ssh-copy-id.1 | 62 | - (tim) [contrib/cygwin/Makefile] Install ssh-copy-id and ssh-copy-id.1 |
diff --git a/channels.c b/channels.c index eb0c61d8b..949392390 100644 --- a/channels.c +++ b/channels.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.c,v 1.298 2009/11/10 04:30:44 dtucker Exp $ */ | 1 | /* $OpenBSD: channels.c,v 1.299 2009/11/11 21:37:03 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * 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, | |||
331 | c->output_filter = NULL; | 331 | c->output_filter = NULL; |
332 | c->filter_ctx = NULL; | 332 | c->filter_ctx = NULL; |
333 | c->filter_cleanup = NULL; | 333 | c->filter_cleanup = NULL; |
334 | c->delayed = 1; /* prevent call to channel_post handler */ | ||
334 | TAILQ_INIT(&c->status_confirms); | 335 | TAILQ_INIT(&c->status_confirms); |
335 | debug("channel %d: new [%s]", found, remote_name); | 336 | debug("channel %d: new [%s]", found, remote_name); |
336 | return c; | 337 | return c; |
@@ -1228,7 +1229,6 @@ channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset) | |||
1228 | int ret; | 1229 | int ret; |
1229 | 1230 | ||
1230 | have = buffer_len(&c->input); | 1231 | have = buffer_len(&c->input); |
1231 | c->delayed = 0; | ||
1232 | debug2("channel %d: pre_dynamic: have %d", c->self, have); | 1232 | debug2("channel %d: pre_dynamic: have %d", c->self, have); |
1233 | /* buffer_dump(&c->input); */ | 1233 | /* buffer_dump(&c->input); */ |
1234 | /* check if the fixed size part of the packet is in buffer. */ | 1234 | /* 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) | |||
1432 | if (c->path != NULL) | 1432 | if (c->path != NULL) |
1433 | nc->path = xstrdup(c->path); | 1433 | nc->path = xstrdup(c->path); |
1434 | 1434 | ||
1435 | if (nextstate == SSH_CHANNEL_DYNAMIC) { | 1435 | if (nextstate != SSH_CHANNEL_DYNAMIC) |
1436 | /* | ||
1437 | * do not call the channel_post handler until | ||
1438 | * this flag has been reset by a pre-handler. | ||
1439 | * otherwise the FD_ISSET calls might overflow | ||
1440 | */ | ||
1441 | nc->delayed = 1; | ||
1442 | } else { | ||
1443 | port_open_helper(nc, rtype); | 1436 | port_open_helper(nc, rtype); |
1444 | } | ||
1445 | } | 1437 | } |
1446 | } | 1438 | } |
1447 | 1439 | ||
@@ -1786,8 +1778,6 @@ channel_check_window(Channel *c) | |||
1786 | static void | 1778 | static void |
1787 | channel_post_open(Channel *c, fd_set *readset, fd_set *writeset) | 1779 | channel_post_open(Channel *c, fd_set *readset, fd_set *writeset) |
1788 | { | 1780 | { |
1789 | if (c->delayed) | ||
1790 | return; | ||
1791 | channel_handle_rfd(c, readset, writeset); | 1781 | channel_handle_rfd(c, readset, writeset); |
1792 | channel_handle_wfd(c, readset, writeset); | 1782 | channel_handle_wfd(c, readset, writeset); |
1793 | if (!compat20) | 1783 | if (!compat20) |
@@ -1919,17 +1909,23 @@ static void | |||
1919 | channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset) | 1909 | channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset) |
1920 | { | 1910 | { |
1921 | static int did_init = 0; | 1911 | static int did_init = 0; |
1922 | u_int i; | 1912 | u_int i, oalloc; |
1923 | Channel *c; | 1913 | Channel *c; |
1924 | 1914 | ||
1925 | if (!did_init) { | 1915 | if (!did_init) { |
1926 | channel_handler_init(); | 1916 | channel_handler_init(); |
1927 | did_init = 1; | 1917 | did_init = 1; |
1928 | } | 1918 | } |
1929 | for (i = 0; i < channels_alloc; i++) { | 1919 | for (i = 0, oalloc = channels_alloc; i < oalloc; i++) { |
1930 | c = channels[i]; | 1920 | c = channels[i]; |
1931 | if (c == NULL) | 1921 | if (c == NULL) |
1932 | continue; | 1922 | continue; |
1923 | if (c->delayed) { | ||
1924 | if (ftab == channel_pre) | ||
1925 | c->delayed = 0; | ||
1926 | else | ||
1927 | continue; | ||
1928 | } | ||
1933 | if (ftab[c->type] != NULL) | 1929 | if (ftab[c->type] != NULL) |
1934 | (*ftab[c->type])(c, readset, writeset); | 1930 | (*ftab[c->type])(c, readset, writeset); |
1935 | channel_garbage_collect(c); | 1931 | channel_garbage_collect(c); |
diff --git a/channels.h b/channels.h index b0f5dc321..4dbeeb6e1 100644 --- a/channels.h +++ b/channels.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.h,v 1.99 2009/10/28 16:38:18 reyk Exp $ */ | 1 | /* $OpenBSD: channels.h,v 1.100 2009/11/11 21:37:03 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -97,7 +97,11 @@ struct Channel { | |||
97 | int wfd_isatty; /* wfd is a tty */ | 97 | int wfd_isatty; /* wfd is a tty */ |
98 | int client_tty; /* (client) TTY has been requested */ | 98 | int client_tty; /* (client) TTY has been requested */ |
99 | int force_drain; /* force close on iEOF */ | 99 | int force_drain; /* force close on iEOF */ |
100 | int delayed; /* fdset hack */ | 100 | int delayed; /* post-select handlers for newly created |
101 | * channels are delayed until the first call | ||
102 | * to a matching pre-select handler. | ||
103 | * this way post-select handlers are not | ||
104 | * accidenly called if a FD gets reused */ | ||
101 | Buffer input; /* data read from socket, to be sent over | 105 | Buffer input; /* data read from socket, to be sent over |
102 | * encrypted connection */ | 106 | * encrypted connection */ |
103 | Buffer output; /* data received over encrypted connection for | 107 | Buffer output; /* data received over encrypted connection for |