mirror of
git://anongit.mindrot.org/openssh.git
synced 2024-11-23 18:23:25 +08: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>
|
||||
* 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;
|
||||
pid_t pid;
|
||||
u_char rnd[256];
|
||||
sigset_t nsigset, osigset;
|
||||
|
||||
/* setup fd set for accept */
|
||||
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++)
|
||||
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
|
||||
* the daemon is killed with a signal.
|
||||
*/
|
||||
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) {
|
||||
setproctitle("%s [listener] %d of %d-%d 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();
|
||||
lameduck = 1;
|
||||
}
|
||||
if (listening <= 0)
|
||||
if (listening <= 0) {
|
||||
sigprocmask(SIG_SETMASK, &osigset, NULL);
|
||||
sighup_restart();
|
||||
}
|
||||
}
|
||||
free(fdset);
|
||||
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)
|
||||
FD_SET(startup_pipes[i], fdset);
|
||||
|
||||
/* Wait in select until there is a connection. */
|
||||
ret = select(maxfd+1, fdset, NULL, NULL, NULL);
|
||||
/* Wait until a connection arrives or a child exits. */
|
||||
ret = pselect(maxfd+1, fdset, NULL, NULL, NULL, &osigset);
|
||||
if (ret == -1 && errno != EINTR)
|
||||
error("select: %.100s", strerror(errno));
|
||||
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 (ret == -1)
|
||||
error("pselect: %.100s", strerror(errno));
|
||||
sigprocmask(SIG_SETMASK, &osigset, NULL);
|
||||
if (received_sigterm)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < options.max_startups; i++) {
|
||||
|
Loading…
Reference in New Issue
Block a user