diff --git a/ChangeLog b/ChangeLog index 19b2d098d..3be37d2c7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,12 @@ [sshconnect.c] don't mention key type in key-changed-warning, since we also print this warning if a new key type appears. ok djm@ + - djm@cvs.openbsd.org 2010/12/15 00:49:27 + [readpass.c] + fix ControlMaster=ask regression + reset SIGCHLD handler before fork (and restore it after) so we don't miss + the the askpass child's exit status. Correct test for exit status/signal to + account for waitpid() failure; with claudio@ ok claudio@ markus@ 20110104 - (djm) [configure.ac Makefile.in] Use mandoc as preferred manpage diff --git a/readpass.c b/readpass.c index bd144c2e3..599c8ef9a 100644 --- a/readpass.c +++ b/readpass.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readpass.c,v 1.47 2006/08/03 03:34:42 deraadt Exp $ */ +/* $OpenBSD: readpass.c,v 1.48 2010/12/15 00:49:27 djm Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -33,6 +33,7 @@ #ifdef HAVE_PATHS_H # include #endif +#include #include #include #include @@ -49,11 +50,12 @@ static char * ssh_askpass(char *askpass, const char *msg) { - pid_t pid; + pid_t pid, ret; size_t len; char *pass; - int p[2], status, ret; + int p[2], status; char buf[1024]; + void (*osigchld)(int); if (fflush(stdout) != 0) error("ssh_askpass: fflush: %s", strerror(errno)); @@ -63,8 +65,10 @@ ssh_askpass(char *askpass, const char *msg) error("ssh_askpass: pipe: %s", strerror(errno)); return NULL; } + osigchld = signal(SIGCHLD, SIG_DFL); if ((pid = fork()) < 0) { error("ssh_askpass: fork: %s", strerror(errno)); + signal(SIGCHLD, osigchld); return NULL; } if (pid == 0) { @@ -77,23 +81,24 @@ ssh_askpass(char *askpass, const char *msg) } close(p[1]); - len = ret = 0; + len = 0; do { - ret = read(p[0], buf + len, sizeof(buf) - 1 - len); - if (ret == -1 && errno == EINTR) + ssize_t r = read(p[0], buf + len, sizeof(buf) - 1 - len); + + if (r == -1 && errno == EINTR) continue; - if (ret <= 0) + if (r <= 0) break; - len += ret; + len += r; } while (sizeof(buf) - 1 - len > 0); buf[len] = '\0'; close(p[0]); - while (waitpid(pid, &status, 0) < 0) + while ((ret = waitpid(pid, &status, 0)) < 0) if (errno != EINTR) break; - - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + signal(SIGCHLD, osigchld); + if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) { memset(buf, 0, sizeof(buf)); return NULL; }