From be3c3a0e468237430ad7d19a33c60d306199a7f2 Mon Sep 17 00:00:00 2001
From: "Gregory P. Smith" <greg@krypto.org>
Date: Sat, 24 Oct 2020 12:07:35 -0700
Subject: [PATCH] bpo-35823: Allow setsid() after vfork() on Linux. (GH-22945)

It should just be a syscall updating a couple of fields in the kernel side
process info.  Confirming, in glibc is appears to be a shim for the setsid
syscall (based on not finding any code implementing anything special for it)
and in uclibc (*much* easier to read) it is clearly just a setsid syscall shim.

A breadcrumb _suggesting_ that it is not allowed on Darwin/macOS comes from
a commit in emacs: https://lists.gnu.org/archive/html/bug-gnu-emacs/2017-04/msg00297.html
but I don't have a way to verify if that is true or not.
As we are not supporting vfork on macOS today I just left a note in a comment.
---
 Modules/_posixsubprocess.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
index b7cba30..8baea31 100644
--- a/Modules/_posixsubprocess.c
+++ b/Modules/_posixsubprocess.c
@@ -38,6 +38,8 @@
 
 #if defined(__linux__) && defined(HAVE_VFORK) && defined(HAVE_SIGNAL_H) && \
     defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
+/* If this is ever expanded to non-Linux platforms, verify what calls are
+ * allowed after vfork(). Ex: setsid() may be disallowed on macOS? */
 # include <signal.h>
 # define VFORK_USABLE 1
 #endif
@@ -712,7 +714,6 @@ struct linux_dirent64 {
 #ifdef VFORK_USABLE
     if (child_sigmask) {
         /* These are checked by our caller; verify them in debug builds. */
-        assert(!call_setsid);
         assert(!call_setuid);
         assert(!call_setgid);
         assert(!call_setgroups);
@@ -997,7 +998,7 @@ struct linux_dirent64 {
     /* Use vfork() only if it's safe. See the comment above child_exec(). */
     sigset_t old_sigs;
     if (preexec_fn == Py_None &&
-        !call_setuid && !call_setgid && !call_setgroups && !call_setsid) {
+        !call_setuid && !call_setgid && !call_setgroups) {
         /* Block all signals to ensure that no signal handlers are run in the
          * child process while it shares memory with us. Note that signals
          * used internally by C libraries won't be blocked by
-- 
1.8.3.1

