[openssh-commits] [openssh] 01/02: upstream: Switch the listening select loop from select() to
git+noreply at mindrot.org
git+noreply at mindrot.org
Fri Jun 4 15:13:19 AEST 2021
This is an automated email from the git hooks/post-receive script.
djm pushed a commit to branch master
in repository openssh.
commit 771f57a8626709f2ad207058efd68fbf30d31553
Author: dtucker at openbsd.org <dtucker at openbsd.org>
Date: Fri Jun 4 05:09:08 2021 +0000
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
---
sshd.c | 45 +++++++++++++++++++++++++++++++--------------
1 file changed, 31 insertions(+), 14 deletions(-)
diff --git a/sshd.c b/sshd.c
index 88497f5f..b1a22e86 100644
--- a/sshd.c
+++ b/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 at cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo at 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++) {
--
To stop receiving notification emails like this one, please contact
djm at mindrot.org.
More information about the openssh-commits
mailing list