Skip to content

Commit 1b3250e

Browse files
committed
Replace call_setgid/call_setuid in _posixsubprocess with gid/uid==-1
1 parent 7169766 commit 1b3250e

File tree

1 file changed

+22
-26
lines changed

1 file changed

+22
-26
lines changed

Modules/_posixsubprocess.c

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,10 @@ reset_signal_handlers(const sigset_t *child_sigmask)
476476
#endif /* VFORK_USABLE */
477477

478478

479+
/* To avoid signeness churn on platforms where gid and uid are unsigned. */
480+
#define RESERVED_GID (gid_t)-1
481+
#define RESERVED_UID (uid_t)-1
482+
479483
/*
480484
* This function is code executed in the child process immediately after
481485
* (v)fork to set things up and call exec().
@@ -518,9 +522,9 @@ child_exec(char *const exec_array[],
518522
int errpipe_read, int errpipe_write,
519523
int close_fds, int restore_signals,
520524
int call_setsid, pid_t pgid_to_set,
521-
int call_setgid, gid_t gid,
522-
int call_setgroups, size_t groups_size, const gid_t *groups,
523-
int call_setuid, uid_t uid, int child_umask,
525+
gid_t gid,
526+
size_t groups_size, const gid_t *groups,
527+
uid_t uid, int child_umask,
524528
const void *child_sigmask,
525529
PyObject *py_fds_to_keep,
526530
PyObject *preexec_fn,
@@ -619,17 +623,17 @@ child_exec(char *const exec_array[],
619623
#endif
620624

621625
#ifdef HAVE_SETGROUPS
622-
if (call_setgroups)
626+
if (groups)
623627
POSIX_CALL(setgroups(groups_size, groups));
624628
#endif /* HAVE_SETGROUPS */
625629

626630
#ifdef HAVE_SETREGID
627-
if (call_setgid)
631+
if (gid != RESERVED_GID)
628632
POSIX_CALL(setregid(gid, gid));
629633
#endif /* HAVE_SETREGID */
630634

631635
#ifdef HAVE_SETREUID
632-
if (call_setuid)
636+
if (uid != RESERVED_UID)
633637
POSIX_CALL(setreuid(uid, uid));
634638
#endif /* HAVE_SETREUID */
635639

@@ -724,9 +728,9 @@ do_fork_exec(char *const exec_array[],
724728
int errpipe_read, int errpipe_write,
725729
int close_fds, int restore_signals,
726730
int call_setsid, pid_t pgid_to_set,
727-
int call_setgid, gid_t gid,
728-
int call_setgroups, size_t groups_size, const gid_t *groups,
729-
int call_setuid, uid_t uid, int child_umask,
731+
gid_t gid,
732+
size_t groups_size, const gid_t *groups,
733+
uid_t uid, int child_umask,
730734
const void *child_sigmask,
731735
PyObject *py_fds_to_keep,
732736
PyObject *preexec_fn,
@@ -737,10 +741,7 @@ do_fork_exec(char *const exec_array[],
737741

738742
#ifdef VFORK_USABLE
739743
if (child_sigmask) {
740-
/* These are checked by our caller; verify them in debug builds. */
741-
assert(!call_setuid);
742-
assert(!call_setgid);
743-
assert(!call_setgroups);
744+
/* Checked by our caller; verify this in debug builds. */
744745
assert(preexec_fn == Py_None);
745746

746747
pid = vfork();
@@ -777,8 +778,8 @@ do_fork_exec(char *const exec_array[],
777778
p2cread, p2cwrite, c2pread, c2pwrite,
778779
errread, errwrite, errpipe_read, errpipe_write,
779780
close_fds, restore_signals, call_setsid, pgid_to_set,
780-
call_setgid, gid, call_setgroups, groups_size, groups,
781-
call_setuid, uid, child_umask, child_sigmask,
781+
gid, groups_size, groups,
782+
uid, child_umask, child_sigmask,
782783
py_fds_to_keep, preexec_fn, preexec_fn_args_tuple);
783784
_exit(255);
784785
return 0; /* Dead code to avoid a potential compiler warning. */
@@ -799,9 +800,7 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
799800
int errpipe_read, errpipe_write, close_fds, restore_signals;
800801
int call_setsid;
801802
pid_t pgid_to_set = -1;
802-
int call_setgid = 0, call_setgroups = 0, call_setuid = 0;
803-
uid_t uid;
804-
gid_t gid, *groups = NULL;
803+
gid_t *groups = NULL;
805804
int child_umask;
806805
PyObject *cwd_obj, *cwd_obj2 = NULL;
807806
const char *cwd;
@@ -951,34 +950,31 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
951950
}
952951
Py_DECREF(elem);
953952
}
954-
call_setgroups = 1;
955953

956954
#else /* HAVE_SETGROUPS */
957955
PyErr_BadInternalCall();
958956
goto cleanup;
959957
#endif /* HAVE_SETGROUPS */
960958
}
961959

960+
gid_t gid = RESERVED_GID;
962961
if (gid_object != Py_None) {
963962
#ifdef HAVE_SETREGID
964963
if (!_Py_Gid_Converter(gid_object, &gid))
965964
goto cleanup;
966965

967-
call_setgid = 1;
968-
969966
#else /* HAVE_SETREGID */
970967
PyErr_BadInternalCall();
971968
goto cleanup;
972969
#endif /* HAVE_SETREUID */
973970
}
974971

972+
uid_t uid = RESERVED_UID;
975973
if (uid_object != Py_None) {
976974
#ifdef HAVE_SETREUID
977975
if (!_Py_Uid_Converter(uid_object, &uid))
978976
goto cleanup;
979977

980-
call_setuid = 1;
981-
982978
#else /* HAVE_SETREUID */
983979
PyErr_BadInternalCall();
984980
goto cleanup;
@@ -1002,7 +998,7 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
1002998
/* Use vfork() only if it's safe. See the comment above child_exec(). */
1003999
sigset_t old_sigs;
10041000
if (preexec_fn == Py_None && allow_vfork &&
1005-
!call_setuid && !call_setgid && !call_setgroups) {
1001+
uid == RESERVED_UID && gid == RESERVED_GID && groups_list == Py_None) {
10061002
/* Block all signals to ensure that no signal handlers are run in the
10071003
* child process while it shares memory with us. Note that signals
10081004
* used internally by C libraries won't be blocked by
@@ -1025,8 +1021,8 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
10251021
p2cread, p2cwrite, c2pread, c2pwrite,
10261022
errread, errwrite, errpipe_read, errpipe_write,
10271023
close_fds, restore_signals, call_setsid, pgid_to_set,
1028-
call_setgid, gid, call_setgroups, num_groups, groups,
1029-
call_setuid, uid, child_umask, old_sigmask,
1024+
gid, num_groups, groups_list != Py_None ? groups : NULL,
1025+
uid, child_umask, old_sigmask,
10301026
py_fds_to_keep, preexec_fn, preexec_fn_args_tuple);
10311027

10321028
/* Parent (original) process */

0 commit comments

Comments
 (0)