summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2009-11-11 21:37:04 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2009-11-11 21:37:04 +0000
commit6b584759798e88e98b87ef87ba4fc1f7740695d8 (patch)
tree70e7e9bbd049b315f81f266481123c68e916e7b5
parent6fa2665a924e0d822d8d099b83a602200bf84911 (diff)
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@
-rw-r--r--usr.bin/ssh/channels.c26
-rw-r--r--usr.bin/ssh/channels.h8
2 files changed, 17 insertions, 17 deletions
diff --git a/usr.bin/ssh/channels.c b/usr.bin/ssh/channels.c
index e4cc30357d5..4bd277f08a4 100644
--- a/usr.bin/ssh/channels.c
+++ b/usr.bin/ssh/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 <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -326,6 +326,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;
@@ -1223,7 +1224,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. */
@@ -1427,16 +1427,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);
- }
}
}
@@ -1762,8 +1754,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)
@@ -1895,17 +1885,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/usr.bin/ssh/channels.h b/usr.bin/ssh/channels.h
index 79fbd227e98..0d0726d7bec 100644
--- a/usr.bin/ssh/channels.h
+++ b/usr.bin/ssh/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 <ylo@cs.hut.fi>
@@ -96,7 +96,11 @@ struct Channel {
int isatty; /* rfd 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