From 39eda6eb6a8364e8df6779e71e0b434eaae3edd5 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sat, 5 Nov 2005 14:52:50 +1100 Subject: [PATCH] - djm@cvs.openbsd.org 2005/10/10 10:23:08 [channels.c channels.h clientloop.c serverloop.c session.c] fix regression I introduced in 4.2: X11 forwardings initiated after a session has exited (e.g. "(sleep 5; xterm) &") would not start. bz #1086 reported by t8m AT centrum.cz; ok markus@ dtucker@ --- ChangeLog | 7 ++++++- channels.c | 9 ++++++--- channels.h | 7 ++++--- clientloop.c | 4 ++-- serverloop.c | 4 ++-- session.c | 37 +++++++++++++++++++++++-------------- 6 files changed, 43 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 10c031042..221301eb9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,11 @@ in order to improve the security of DSA you need to change more components of DSA key generation (e.g. the internal SHA1 hash); ok deraadt + - djm@cvs.openbsd.org 2005/10/10 10:23:08 + [channels.c channels.h clientloop.c serverloop.c session.c] + fix regression I introduced in 4.2: X11 forwardings initiated after + a session has exited (e.g. "(sleep 5; xterm) &") would not start. + bz #1086 reported by t8m AT centrum.cz; ok markus@ dtucker@ 20051102 - (dtucker) [openbsd-compat/bsd-misc.c] Bug #1108: fix broken strdup(). @@ -3140,4 +3145,4 @@ - (djm) Trim deprecated options from INSTALL. Mention UsePAM - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu -$Id: ChangeLog,v 1.3927 2005/11/05 03:52:18 djm Exp $ +$Id: ChangeLog,v 1.3928 2005/11/05 03:52:50 djm Exp $ diff --git a/channels.c b/channels.c index af858b4a5..b0bc77901 100644 --- a/channels.c +++ b/channels.c @@ -39,7 +39,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: channels.c,v 1.224 2005/09/07 08:53:53 markus Exp $"); +RCSID("$OpenBSD: channels.c,v 1.225 2005/10/10 10:23:08 djm Exp $"); #include "ssh.h" #include "ssh1.h" @@ -269,6 +269,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, c->force_drain = 0; c->single_connection = 0; c->detach_user = NULL; + c->detach_close = 0; c->confirm = NULL; c->confirm_ctx = NULL; c->input_filter = NULL; @@ -628,7 +629,7 @@ channel_register_confirm(int id, channel_callback_fn *fn, void *ctx) c->confirm_ctx = ctx; } void -channel_register_cleanup(int id, channel_callback_fn *fn) +channel_register_cleanup(int id, channel_callback_fn *fn, int do_close) { Channel *c = channel_lookup(id); @@ -637,6 +638,7 @@ channel_register_cleanup(int id, channel_callback_fn *fn) return; } c->detach_user = fn; + c->detach_close = do_close; } void channel_cancel_cleanup(int id) @@ -648,6 +650,7 @@ channel_cancel_cleanup(int id) return; } c->detach_user = NULL; + c->detach_close = 0; } void channel_register_filter(int id, channel_filter_fn *fn) @@ -1666,7 +1669,7 @@ channel_garbage_collect(Channel *c) if (c == NULL) return; if (c->detach_user != NULL) { - if (!chan_is_dead(c, 0)) + if (!chan_is_dead(c, c->detach_close)) return; debug2("channel %d: gc: notify user", c->self); c->detach_user(c->self, NULL); diff --git a/channels.h b/channels.h index 1cb2c3a34..7e1cc7c5a 100644 --- a/channels.h +++ b/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.79 2005/07/17 06:49:04 djm Exp $ */ +/* $OpenBSD: channels.h,v 1.80 2005/10/10 10:23:08 djm Exp $ */ /* * Author: Tatu Ylonen @@ -106,8 +106,9 @@ struct Channel { /* callback */ channel_callback_fn *confirm; - channel_callback_fn *detach_user; void *confirm_ctx; + channel_callback_fn *detach_user; + int detach_close; /* filter */ channel_filter_fn *input_filter; @@ -163,7 +164,7 @@ void channel_stop_listening(void); void channel_send_open(int); void channel_request_start(int, char *, int); -void channel_register_cleanup(int, channel_callback_fn *); +void channel_register_cleanup(int, channel_callback_fn *, int); void channel_register_confirm(int, channel_callback_fn *, void *); void channel_register_filter(int, channel_filter_fn *); void channel_cancel_cleanup(int); diff --git a/clientloop.c b/clientloop.c index da5bfd7bd..fed684956 100644 --- a/clientloop.c +++ b/clientloop.c @@ -59,7 +59,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: clientloop.c,v 1.142 2005/09/09 19:18:05 markus Exp $"); +RCSID("$OpenBSD: clientloop.c,v 1.143 2005/10/10 10:23:08 djm Exp $"); #include "ssh.h" #include "ssh1.h" @@ -1379,7 +1379,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) simple_escape_filter); if (session_ident != -1) channel_register_cleanup(session_ident, - client_channel_closed); + client_channel_closed, 0); } else { /* Check if we should immediately send eof on stdin. */ client_check_initial_eof_on_stdin(); diff --git a/serverloop.c b/serverloop.c index d2eff170a..17608c238 100644 --- a/serverloop.c +++ b/serverloop.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: serverloop.c,v 1.118 2005/07/17 07:17:55 djm Exp $"); +RCSID("$OpenBSD: serverloop.c,v 1.119 2005/10/10 10:23:08 djm Exp $"); #include "xmalloc.h" #include "packet.h" @@ -900,7 +900,7 @@ server_request_session(void) channel_free(c); return NULL; } - channel_register_cleanup(c->self, session_close_by_channel); + channel_register_cleanup(c->self, session_close_by_channel, 0); return c; } diff --git a/session.c b/session.c index 2a1a25ac4..5e6627cb0 100644 --- a/session.c +++ b/session.c @@ -33,7 +33,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.186 2005/07/25 11:59:40 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.187 2005/10/10 10:23:08 djm Exp $"); #include "ssh.h" #include "ssh1.h" @@ -2156,7 +2156,6 @@ static void session_exit_message(Session *s, int status) { Channel *c; - u_int i; if ((c = channel_lookup(s->chanid)) == NULL) fatal("session_exit_message: session %d: no channel %d", @@ -2186,7 +2185,15 @@ session_exit_message(Session *s, int status) /* disconnect channel */ debug("session_exit_message: release channel %d", s->chanid); - channel_cancel_cleanup(s->chanid); + s->pid = 0; + + /* + * Adjust cleanup callback attachment to send close messages when + * the channel gets EOF. The session will be then be closed + * by session_close_by_channel when the childs close their fds. + */ + channel_register_cleanup(c->self, session_close_by_channel, 1); + /* * emulate a write failure with 'chan_write_failed', nobody will be * interested in data we write. @@ -2195,15 +2202,6 @@ session_exit_message(Session *s, int status) */ if (c->ostate != CHAN_OUTPUT_CLOSED) chan_write_failed(c); - s->chanid = -1; - - /* Close any X11 listeners associated with this session */ - if (s->x11_chanids != NULL) { - for (i = 0; s->x11_chanids[i] != -1; i++) { - session_close_x11(s->x11_chanids[i]); - s->x11_chanids[i] = -1; - } - } } void @@ -2247,7 +2245,8 @@ session_close_by_pid(pid_t pid, int status) } if (s->chanid != -1) session_exit_message(s, status); - session_close(s); + if (s->ttyfd != -1) + session_pty_cleanup(s); } /* @@ -2258,6 +2257,7 @@ void session_close_by_channel(int id, void *arg) { Session *s = session_by_channel(id); + u_int i; if (s == NULL) { debug("session_close_by_channel: no session for id %d", id); @@ -2277,6 +2277,15 @@ session_close_by_channel(int id, void *arg) } /* detach by removing callback */ channel_cancel_cleanup(s->chanid); + + /* Close any X11 listeners associated with this session */ + if (s->x11_chanids != NULL) { + for (i = 0; s->x11_chanids[i] != -1; i++) { + session_close_x11(s->x11_chanids[i]); + s->x11_chanids[i] = -1; + } + } + s->chanid = -1; session_close(s); } @@ -2371,7 +2380,7 @@ session_setup_x11fwd(Session *s) } for (i = 0; s->x11_chanids[i] != -1; i++) { channel_register_cleanup(s->x11_chanids[i], - session_close_single_x11); + session_close_single_x11, 0); } /* Set up a suitable value for the DISPLAY variable. */