[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