From 1b1e39c080a01a973d6f12625408ca888484a665 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Thu, 14 Jun 2007 22:48:06 +0000 Subject: when waiting for the multiplex exit status, read until the master end writes an entire int of data *and* closes the client_fd; fixes mux regression spotted by dtucker, ok dtucker@ --- usr.bin/ssh/ssh.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'usr.bin/ssh') diff --git a/usr.bin/ssh/ssh.c b/usr.bin/ssh/ssh.c index 3aa94789bc8..ba269aa4be8 100644 --- a/usr.bin/ssh/ssh.c +++ b/usr.bin/ssh/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.299 2007/06/14 21:43:25 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.300 2007/06/14 22:48:05 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1286,7 +1286,7 @@ static void control_client(const char *path) { struct sockaddr_un addr; - int i, r, fd, sock, exitval, num_env; + int i, r, fd, sock, exitval[2], num_env; Buffer m; char *term; extern char **environ; @@ -1435,10 +1435,16 @@ control_client(const char *path) if (tty_flag) enter_raw_mode(); - /* Stick around until the controlee closes the client_fd */ - exitval = 0; + /* + * Stick around until the controlee closes the client_fd. + * Before it does, it is expected to write this process' exit + * value (one int). This process must read the value and wait for + * the closure of the client_fd; if this one closes early, the + * multiplex master will terminate early too (possibly losing data). + */ + exitval[0] = 0; for (i = 0; !control_client_terminate && i < (int)sizeof(exitval);) { - r = read(sock, (char *)&exitval + i, sizeof(exitval) - i); + r = read(sock, (char *)exitval + i, sizeof(exitval) - i); if (r == 0) { debug2("Received EOF from master"); break; @@ -1450,21 +1456,23 @@ control_client(const char *path) } i += r; } + close(sock); leave_raw_mode(); - + if (i > (int)sizeof(int)) + fatal("%s: master returned too much data (%d > %lu)", + __func__, i, sizeof(int)); if (control_client_terminate) { debug2("Exiting on signal %d", control_client_terminate); - exitval = 255; - } else if (i < (int)sizeof(exitval)) { + exitval[0] = 255; + } else if (i < (int)sizeof(int)) { debug2("Control master terminated unexpectedly"); - exitval = 255; + exitval[0] = 255; } else - debug2("Received exit status from master %d", exitval); + debug2("Received exit status from master %d", exitval[0]); if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET) - fprintf(stderr, "Shared connection to %s closed.\r\n", - host); + fprintf(stderr, "Shared connection to %s closed.\r\n", host); - exit(exitval); + exit(exitval[0]); } -- cgit v1.2.3