[openssh-commits] [openssh] 01/02: Fix race in pselect replacement code.

git+noreply at mindrot.org git+noreply at mindrot.org
Fri Aug 20 08:40:34 AEST 2021


This is an automated email from the git hooks/post-receive script.

dtucker pushed a commit to branch master
in repository openssh.

commit 10e45654cff221ca60fd35ee069df67208fcf415
Author: Darren Tucker <dtucker at dtucker.net>
Date:   Fri Aug 20 08:30:42 2021 +1000

    Fix race in pselect replacement code.
    
    On the second and subsequent calls to pselect the notify_pipe was not
    added to the select readset, opening up a race that om G. Christensen
    discovered on multiprocessor Solaris <=9 systems.
    
    Also reinitialize notify_pipe if the pid changes.  This will prevent a
    parent and child from using the same FD, although this is not an issue
    in the current structure it might be in future.
---
 openbsd-compat/bsd-pselect.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/openbsd-compat/bsd-pselect.c b/openbsd-compat/bsd-pselect.c
index da34b41d..983427aa 100644
--- a/openbsd-compat/bsd-pselect.c
+++ b/openbsd-compat/bsd-pselect.c
@@ -73,6 +73,7 @@ notify_setup_fd(int *fd)
  * we write to this pipe if a SIGCHLD is caught in order to avoid
  * the race between select() and child_terminated
  */
+static pid_t notify_pid;
 static int notify_pipe[2];
 static void
 notify_setup(void)
@@ -81,6 +82,15 @@ notify_setup(void)
 
 	if (initialized)
 		return;
+	if (notify_pid == 0)
+		debug3_f("initializing");
+	else {
+		debug3_f("pid changed, reinitializing");
+		if (notify_pipe[0] != -1)
+			close(notify_pipe[0]);
+		if (notify_pipe[1] != -1)
+			close(notify_pipe[1]);
+	}
 	if (pipe(notify_pipe) == -1) {
 		error("pipe(notify_pipe) failed %s", strerror(errno));
 	} else if (notify_setup_fd(&notify_pipe[0]) == -1 ||
@@ -91,6 +101,9 @@ notify_setup(void)
 	} else {
 		set_nonblock(notify_pipe[0]);
 		set_nonblock(notify_pipe[1]);
+		notify_pid = getpid();
+		debug3_f("pid %d saved %d pipe0 %d pipe1 %d", getpid(),
+		    notify_pid, notify_pipe[0], notify_pipe[1]);
 		initialized = 1;
 		return;
 	}
@@ -159,15 +172,16 @@ pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 		if (sig == SIGKILL || sig == SIGSTOP || sigismember(mask, sig))
 			continue;
 		if (sigaction(sig, NULL, &sa) == 0 &&
-		    sa.sa_handler != SIG_IGN && sa.sa_handler != SIG_DFL &&
-		    sa.sa_handler != sig_handler) {
+		    sa.sa_handler != SIG_IGN && sa.sa_handler != SIG_DFL) {
+			unmasked = 1;
+			if (sa.sa_handler == sig_handler)
+				continue;
 			sa.sa_handler = sig_handler;
 			if (sigaction(sig, &sa, &osa) == 0) {
 				debug3_f("installing signal handler for %s, "
 				    "previous %p", strsignal(sig),
 				     osa.sa_handler);
 				saved_sighandler[sig] = osa.sa_handler;
-				unmasked = 1;
 			}
 		}
 	}
@@ -183,7 +197,8 @@ pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
 	saved_errno = errno;
 	sigprocmask(SIG_SETMASK, &osig, NULL);
 
-	notify_done(readfds);
+	if (unmasked)
+		notify_done(readfds);
 	errno = saved_errno;
 	return ret;
 }

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list