From 504558243c7c78af5317ced09513611595193f6b Mon Sep 17 00:00:00 2001 From: dtucker Date: Mon, 25 Jun 2007 08:59:17 +0000 Subject: [PATCH] - 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@ --- ChangeLog | 5 +++++ ssh.c | 34 +++++++++++++++++++++------------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index e198f664..619bd8d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,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@ 20070614 - (dtucker) [cipher-ctr.c umac.c openbsd-compat/openssl-compat.h] Move the diff --git a/ssh.c b/ssh.c index ab9da1e9..449ec256 100644 --- a/ssh.c +++ b/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 @@ -1311,7 +1311,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; @@ -1460,10 +1460,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; @@ -1475,21 +1481,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]); } -- 2.45.2