summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@zip.com.au>2007-06-25 18:59:31 +1000
committerDarren Tucker <dtucker@zip.com.au>2007-06-25 18:59:31 +1000
commit202c17be30b34a27ba831ed8ad22bffe46a24ae6 (patch)
treeeaf9cdd122bba6b7e9ad37befdb374a32f994486
parent20c4012e60128ad1b206b05423d30880651bcb5a (diff)
- djm@cvs.openbsd.org 2007/06/14 22:48:05
[ssh.c] 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@
-rw-r--r--ChangeLog7
-rw-r--r--ssh.c31
2 files changed, 26 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 1c254ac3..d305669c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,11 @@
- djm@cvs.openbsd.org 2007/06/14 21:43:25
[ssh.c]
handle EINTR when waiting for mux exit status properly
+ - djm@cvs.openbsd.org 2007/06/14 22:48:05
+ [ssh.c]
+ 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@
20070612
- (dtucker) OpenBSD CVS Sync
@@ -2882,4 +2887,4 @@
OpenServer 6 and add osr5bigcrypt support so when someone migrates
passwords between UnixWare and OpenServer they will still work. OK dtucker@
-$Id: ChangeLog,v 1.4635.2.14 2007/06/25 08:43:03 dtucker Exp $
+$Id: ChangeLog,v 1.4635.2.15 2007/06/25 08:59:31 dtucker Exp $
diff --git a/ssh.c b/ssh.c
index 446184ca..43932895 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1307,7 +1307,7 @@ static void
control_client(const char *path)
{
struct sockaddr_un addr;
- int i, r, fd, sock, exitval, num_env, addr_len;
+ int i, r, fd, sock, exitval[2], num_env, addr_len;
Buffer m;
char *term;
extern char **environ;
@@ -1456,10 +1456,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;
@@ -1471,20 +1477,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, "Connection to master closed.\r\n");
+ fprintf(stderr, "Shared connection to %s closed.\r\n", host);
- exit(exitval);
+ exit(exitval[0]);
}