From: Tim Wickberg <tim@schedmd.com>
Date: Wed Oct 11 12:45:25 2023 -0600
Subject: [PATCH 17/19]Expose drop_privileges() / reclaim_privileges().
Patch-mainline: Upstream
Git-repo: https://github.com/SchedMD/slurm
Git-commit: a3fd54313c5383c8689f8004be3e96e16f74a572
References: bsc##1216207, CVE-2023-41914
Signed-off-by: Egbert Eich <eich@suse.de>

---
 src/slurmd/slurmstepd/mgr.c | 45 ++++++++++++++++-----------------------------
 src/slurmd/slurmstepd/mgr.h | 12 ++++++++++++
 2 files changed, 28 insertions(+), 29 deletions(-)

diff --git a/src/slurmd/slurmstepd/mgr.c b/src/slurmd/slurmstepd/mgr.c
index 4fba18f390..09ad132ffc 100644
--- a/src/slurmd/slurmstepd/mgr.c
+++ b/src/slurmd/slurmstepd/mgr.c
@@ -128,14 +128,6 @@ static int mgr_sigarray[] = {
 	SIGUSR2, SIGALRM, SIGHUP, 0
 };
 
-struct priv_state {
-	uid_t	saved_uid;
-	gid_t	saved_gid;
-	gid_t *	gid_list;
-	int	ngids;
-	char	saved_cwd [4096];
-};
-
 step_complete_t step_complete = {
 	PTHREAD_COND_INITIALIZER,
 	PTHREAD_MUTEX_INITIALIZER,
@@ -173,9 +165,6 @@ static int  _become_user(stepd_step_rec_t *job, struct priv_state *ps);
 static void  _set_prio_process (stepd_step_rec_t *job);
 static void _set_job_log_prefix(stepd_step_rec_t *job);
 static int  _setup_normal_io(stepd_step_rec_t *job);
-static int  _drop_privileges(stepd_step_rec_t *job, bool do_setuid,
-			     struct priv_state *state, bool get_list);
-static int  _reclaim_privileges(struct priv_state *state);
 static void _send_launch_resp(stepd_step_rec_t *job, int rc);
 static int  _slurmd_job_log_init(stepd_step_rec_t *job);
 static void _wait_for_io(stepd_step_rec_t *job);
@@ -516,7 +505,7 @@ _setup_normal_io(stepd_step_rec_t *job)
 	 * descriptors (which may be connected to files), then
 	 * reclaim privileges.
 	 */
-	if (_drop_privileges(job, true, &sprivs, true) < 0)
+	if (drop_privileges(job, true, &sprivs, true) < 0)
 		return ESLURMD_SET_UID_OR_GID_ERROR;
 
 	if (io_init_tasks_stdio(job) != SLURM_SUCCESS) {
@@ -630,7 +619,7 @@ _setup_normal_io(stepd_step_rec_t *job)
 	}
 
 claim:
-	if (_reclaim_privileges(&sprivs) < 0) {
+	if (reclaim_privileges(&sprivs) < 0) {
 		error("sete{u/g}id(%lu/%lu): %m",
 		      (u_long) sprivs.saved_uid, (u_long) sprivs.saved_gid);
 	}
@@ -1410,14 +1399,14 @@ fail1:
 static int _pre_task_child_privileged(
 	stepd_step_rec_t *job, int taskid, struct priv_state *sp)
 {
-	if (_reclaim_privileges(sp) < 0)
+	if (reclaim_privileges(sp) < 0)
 		return SLURM_ERROR;
 
 	if (spank_task_privileged(job, taskid) < 0)
 		return error("spank_task_init_privileged failed");
 
 	/* sp->gid_list should already be initialized */
-	return (_drop_privileges(job, true, sp, false));
+	return (drop_privileges(job, true, sp, false));
 }
 
 struct exec_wait_info {
@@ -1620,7 +1609,7 @@ _fork_all_tasks(stepd_step_rec_t *job, bool *io_initialized)
 	/* Temporarily drop effective privileges, except for the euid.
 	 * We need to wait until after pam_setup() to drop euid.
 	 */
-	if (_drop_privileges (job, false, &sprivs, true) < 0)
+	if (drop_privileges (job, false, &sprivs, true) < 0)
 		return ESLURMD_SET_UID_OR_GID_ERROR;
 
 	if (pam_setup(job->user_name, conf->hostname)
@@ -1632,7 +1621,7 @@ _fork_all_tasks(stepd_step_rec_t *job, bool *io_initialized)
 	/*
 	 * Reclaim privileges to do the io setup
 	 */
-	_reclaim_privileges (&sprivs);
+	reclaim_privileges(&sprivs);
 	if (rc)
 		goto fail1; /* pam_setup error */
 
@@ -1661,8 +1650,8 @@ _fork_all_tasks(stepd_step_rec_t *job, bool *io_initialized)
 	/*
 	 * Temporarily drop effective privileges
 	 */
-	if (_drop_privileges (job, true, &sprivs, true) < 0) {
-		error ("_drop_privileges: %m");
+	if (drop_privileges (job, true, &sprivs, true) < 0) {
+		error ("drop_privileges: %m");
 		rc = SLURM_ERROR;
 		goto fail2;
 	}
@@ -1733,7 +1722,7 @@ _fork_all_tasks(stepd_step_rec_t *job, bool *io_initialized)
 			 * Reclaim privileges for the child and call any plugin
 			 * hooks that may require elevated privs
 			 * sprivs.gid_list is already set from the
-			 * _drop_privileges call above, no not reinitialize.
+			 * drop_privileges call above, no not reinitialize.
 			 * NOTE: Only put things in here that are self contained
 			 * and belong in the child.
 			 */
@@ -1797,7 +1786,7 @@ _fork_all_tasks(stepd_step_rec_t *job, bool *io_initialized)
 	/*
 	 * Reclaim privileges
 	 */
-	if (_reclaim_privileges (&sprivs) < 0) {
+	if (reclaim_privileges(&sprivs) < 0) {
 		error ("Unable to reclaim privileges");
 		/* Don't bother erroring out here */
 	}
@@ -1888,7 +1877,7 @@ fail4:
 		error ("Unable to return to working directory");
 	}
 fail3:
-	_reclaim_privileges (&sprivs);
+	reclaim_privileges (&sprivs);
 fail2:
 	FREE_NULL_LIST(exec_wait_list);
 	io_close_task_fds(job);
@@ -2454,9 +2443,8 @@ _send_complete_batch_script_msg(stepd_step_rec_t *job, int err, int status)
 /* If get_list is false make sure ps->gid_list is initialized before
  * hand to prevent xfree.
  */
-static int
-_drop_privileges(stepd_step_rec_t *job, bool do_setuid,
-		 struct priv_state *ps, bool get_list)
+extern int drop_privileges(stepd_step_rec_t *job, bool do_setuid,
+			   struct priv_state *ps, bool get_list)
 {
 	ps->saved_uid = getuid();
 	ps->saved_gid = getgid();
@@ -2512,8 +2500,7 @@ _drop_privileges(stepd_step_rec_t *job, bool do_setuid,
 	return SLURM_SUCCESS;
 }
 
-static int
-_reclaim_privileges(struct priv_state *ps)
+extern int reclaim_privileges(struct priv_state *ps)
 {
 	int rc = SLURM_SUCCESS;
 
@@ -2854,8 +2841,8 @@ _run_script_as_user(const char *name, const char *path, stepd_step_rec_t *job,
 		argv[1] = NULL;
 
 		sprivs.gid_list = NULL;	/* initialize to prevent xfree */
-		if (_drop_privileges(job, true, &sprivs, false) < 0) {
-			error("run_script_as_user _drop_privileges: %m");
+		if (drop_privileges(job, true, &sprivs, false) < 0) {
+			error("run_script_as_user drop_privileges: %m");
 			/* child process, should not return */
 			exit(127);
 		}
diff --git a/src/slurmd/slurmstepd/mgr.h b/src/slurmd/slurmstepd/mgr.h
index a5f81106d5..df9015b620 100644
--- a/src/slurmd/slurmstepd/mgr.h
+++ b/src/slurmd/slurmstepd/mgr.h
@@ -85,4 +85,16 @@ int job_manager(stepd_step_rec_t *job);
 extern void init_initgroups(int);
 
 
+struct priv_state {
+	uid_t saved_uid;
+	gid_t saved_gid;
+	gid_t *gid_list;
+	int ngids;
+	char saved_cwd[4096];
+};
+
+extern int drop_privileges(stepd_step_rec_t *step, bool do_setuid,
+			   struct priv_state *state, bool get_list);
+extern int reclaim_privileges(struct priv_state *state);
+
 #endif
