mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-31 01:35:11 +02:00
upstream: Switch the listening select loop from select() to
pselect() and mask signals while checking signal flags, umasking for pselect and restoring afterwards. Also restore signals before sighup_restart so they don't remain blocked after restart. This prevents a race where a SIGTERM or SIGHUP can arrive between checking the flag and calling select (eg if sshd is processing a new connection) resulting in sshd not shutting down until the next time it receives a new connection. bz#2158, with & ok djm@ OpenBSD-Commit-ID: bf85bf880fd78e00d7478657644fcda97b9a936f
This commit is contained in:
parent
f64f8c00d1
commit
771f57a862
45
sshd.c
45
sshd.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sshd.c,v 1.573 2021/05/07 03:09:38 djm Exp $ */
|
/* $OpenBSD: sshd.c,v 1.574 2021/06/04 05:09:08 dtucker Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
@ -1141,6 +1141,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
|
|||||||
socklen_t fromlen;
|
socklen_t fromlen;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
u_char rnd[256];
|
u_char rnd[256];
|
||||||
|
sigset_t nsigset, osigset;
|
||||||
|
|
||||||
/* setup fd set for accept */
|
/* setup fd set for accept */
|
||||||
fdset = NULL;
|
fdset = NULL;
|
||||||
@ -1154,11 +1155,32 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
|
|||||||
for (i = 0; i < options.max_startups; i++)
|
for (i = 0; i < options.max_startups; i++)
|
||||||
startup_pipes[i] = -1;
|
startup_pipes[i] = -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare signal mask that we use to block signals that might set
|
||||||
|
* received_sigterm or received_sighup, so that we are guaranteed
|
||||||
|
* to immediately wake up the pselect if a signal is received after
|
||||||
|
* the flag is checked.
|
||||||
|
*/
|
||||||
|
sigemptyset(&nsigset);
|
||||||
|
sigaddset(&nsigset, SIGHUP);
|
||||||
|
sigaddset(&nsigset, SIGCHLD);
|
||||||
|
sigaddset(&nsigset, SIGTERM);
|
||||||
|
sigaddset(&nsigset, SIGQUIT);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stay listening for connections until the system crashes or
|
* Stay listening for connections until the system crashes or
|
||||||
* the daemon is killed with a signal.
|
* the daemon is killed with a signal.
|
||||||
*/
|
*/
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
sigprocmask(SIG_BLOCK, &nsigset, &osigset);
|
||||||
|
if (received_sigterm) {
|
||||||
|
logit("Received signal %d; terminating.",
|
||||||
|
(int) received_sigterm);
|
||||||
|
close_listen_socks();
|
||||||
|
if (options.pid_file != NULL)
|
||||||
|
unlink(options.pid_file);
|
||||||
|
exit(received_sigterm == SIGTERM ? 0 : 255);
|
||||||
|
}
|
||||||
if (ostartups != startups) {
|
if (ostartups != startups) {
|
||||||
setproctitle("%s [listener] %d of %d-%d startups",
|
setproctitle("%s [listener] %d of %d-%d startups",
|
||||||
listener_proctitle, startups,
|
listener_proctitle, startups,
|
||||||
@ -1171,8 +1193,10 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
|
|||||||
close_listen_socks();
|
close_listen_socks();
|
||||||
lameduck = 1;
|
lameduck = 1;
|
||||||
}
|
}
|
||||||
if (listening <= 0)
|
if (listening <= 0) {
|
||||||
|
sigprocmask(SIG_SETMASK, &osigset, NULL);
|
||||||
sighup_restart();
|
sighup_restart();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(fdset);
|
free(fdset);
|
||||||
fdset = xcalloc(howmany(maxfd + 1, NFDBITS),
|
fdset = xcalloc(howmany(maxfd + 1, NFDBITS),
|
||||||
@ -1184,19 +1208,12 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
|
|||||||
if (startup_pipes[i] != -1)
|
if (startup_pipes[i] != -1)
|
||||||
FD_SET(startup_pipes[i], fdset);
|
FD_SET(startup_pipes[i], fdset);
|
||||||
|
|
||||||
/* Wait in select until there is a connection. */
|
/* Wait until a connection arrives or a child exits. */
|
||||||
ret = select(maxfd+1, fdset, NULL, NULL, NULL);
|
ret = pselect(maxfd+1, fdset, NULL, NULL, NULL, &osigset);
|
||||||
if (ret == -1 && errno != EINTR)
|
if (ret == -1 && errno != EINTR)
|
||||||
error("select: %.100s", strerror(errno));
|
error("pselect: %.100s", strerror(errno));
|
||||||
if (received_sigterm) {
|
sigprocmask(SIG_SETMASK, &osigset, NULL);
|
||||||
logit("Received signal %d; terminating.",
|
if (received_sigterm)
|
||||||
(int) received_sigterm);
|
|
||||||
close_listen_socks();
|
|
||||||
if (options.pid_file != NULL)
|
|
||||||
unlink(options.pid_file);
|
|
||||||
exit(received_sigterm == SIGTERM ? 0 : 255);
|
|
||||||
}
|
|
||||||
if (ret == -1)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (i = 0; i < options.max_startups; i++) {
|
for (i = 0; i < options.max_startups; i++) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user