diff --git a/ssh.c b/ssh.c index 2b7b2bcba..ec3ce1208 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.644 2026/10/30 06:47:17 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.645 2026/10/30 08:17:19 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -2512,7 +2512,10 @@ main_sigchld_handler(int sig) int status; while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || - (pid == -1 && errno == EINTR)) - ; + (pid == -1 && errno == EINTR)) { + /* Once reaped, the ProxyCommand's pid may be reused. */ + if (pid > 0) + ssh_proxy_command_reaped(pid); + } errno = save_errno; } diff --git a/sshconnect.c b/sshconnect.c index de1f89b45..8c7ff4494 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.c,v 1.390 2026/10/30 07:44:23 djm Exp $ */ +/* $OpenBSD: sshconnect.c,v 1.391 2026/10/30 08:17:19 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -60,7 +60,7 @@ struct sshkey *previous_host_key = NULL; static int matching_host_key_dns = 0; -static pid_t proxy_command_pid = 0; +static volatile pid_t proxy_command_pid = 0; /* import */ extern int debug_flag; @@ -301,15 +301,33 @@ ssh_proxy_connect(struct ssh *ssh, const char *host, const char *host_arg, return 0; } +/* + * Called from the SIGCHLD handler for each child it reaps. Forget the + * proxy command once it has been reaped, as its pid may be reused. + */ +void +ssh_proxy_command_reaped(pid_t pid) +{ + if (pid == proxy_command_pid) + proxy_command_pid = 0; +} + void ssh_kill_proxy_command(void) { + sigset_t nset, oset; + /* * Send SIGHUP to proxy command if used. We don't wait() in - * case it hangs and instead rely on init to reap the child + * case it hangs and instead rely on init to reap the child. + * Block SIGCHLD so it can't be reaped between the check and kill(). */ + sigemptyset(&nset); + sigaddset(&nset, SIGCHLD); + sigprocmask(SIG_BLOCK, &nset, &oset); if (proxy_command_pid > 1) kill(proxy_command_pid, SIGHUP); + sigprocmask(SIG_SETMASK, &oset, NULL); } #ifdef HAVE_IFADDRS_H diff --git a/sshconnect.h b/sshconnect.h index aad13c20c..41f711311 100644 --- a/sshconnect.h +++ b/sshconnect.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect.h,v 1.52 2026/08/03 06:47:24 djm Exp $ */ +/* $OpenBSD: sshconnect.h,v 1.53 2026/10/30 08:17:19 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -74,6 +74,7 @@ int ssh_connect(struct ssh *, const char *, const char *, struct addrinfo *, struct sockaddr_storage *, u_short, int, int *, int); void ssh_kill_proxy_command(void); +void ssh_proxy_command_reaped(pid_t); void ssh_login(struct ssh *, Sensitive *, const char *, struct sockaddr_storage *, u_short, struct passwd *, int,