From: Alejandro Sanchez <alex@schedmd.com>
Date: Wed Oct 11 12:45:25 2023 -0600
Subject: [PATCH 14/19]Drop/reclaim privileges to prevent security issue with H5Fcreate().
Patch-mainline: Upstream
Git-repo: https://github.com/SchedMD/slurm
Git-commit: 0068aaf60a2451599f1a7fc3017340172a049f24
References: bsc#1216207
Signed-off-by: Egbert Eich <eich@suse.de>

Copy _{drop,reclaim}_privileges() to hdf5 plugin. Ignore the style issues,
just copy this verbatim. Will be cleaned up further on master.

Co-authored-by: Tim Wickberg <tim@schedmd.com>
---
 .../hdf5/acct_gather_profile_hdf5.c                | 106 ++++++++++++++++++++-
 1 file changed, 105 insertions(+), 1 deletion(-)

diff --git a/src/plugins/acct_gather_profile/hdf5/acct_gather_profile_hdf5.c b/src/plugins/acct_gather_profile/hdf5/acct_gather_profile_hdf5.c
index 57eeaa907f..d5a972d7c3 100644
--- a/src/plugins/acct_gather_profile/hdf5/acct_gather_profile_hdf5.c
+++ b/src/plugins/acct_gather_profile/hdf5/acct_gather_profile_hdf5.c
@@ -44,6 +44,7 @@
  *  Copyright (C) 2002 The Regents of the University of California.
 \*****************************************************************************/
 
+#include <grp.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -100,6 +101,14 @@ const char plugin_name[] = "AcctGatherProfile hdf5 plugin";
 const char plugin_type[] = "acct_gather_profile/hdf5";
 const uint32_t plugin_version = SLURM_VERSION_NUMBER;
 
+struct priv_state {
+	uid_t	saved_uid;
+	gid_t	saved_gid;
+	gid_t * gid_list;
+	int	ngids;
+	char	saved_cwd [4096];
+};
+
 typedef struct {
 	char *dir;
 	uint32_t def;
@@ -132,6 +141,88 @@ static table_t *tables = NULL;
 static size_t   tables_max_len = 0;
 static size_t   tables_cur_len = 0;
 
+/* 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)
+{
+	ps->saved_uid = getuid();
+	ps->saved_gid = getgid();
+
+	if (!getcwd (ps->saved_cwd, sizeof (ps->saved_cwd))) {
+		error ("Unable to get current working directory: %m");
+		strlcpy(ps->saved_cwd, "/tmp", sizeof(ps->saved_cwd));
+	}
+
+	ps->ngids = getgroups(0, NULL);
+	if (ps->ngids == -1) {
+		error("%s: getgroups(): %m", __func__);
+		return -1;
+	}
+	if (get_list) {
+		ps->gid_list = (gid_t *) xmalloc(ps->ngids * sizeof(gid_t));
+
+		if (getgroups(ps->ngids, ps->gid_list) == -1) {
+			error("%s: couldn't get %d groups: %m",
+			      __func__, ps->ngids);
+			xfree(ps->gid_list);
+			return -1;
+		}
+	}
+
+	/*
+	 * No need to drop privileges if we're not running as root
+	 */
+	if (getuid() != (uid_t) 0)
+		return SLURM_SUCCESS;
+
+	if (setegid(job->gid) < 0) {
+		error("setegid: %m");
+		return -1;
+	}
+
+	if (setgroups(job->ngids, job->gids) < 0) {
+		error("setgroups: %m");
+		return -1;
+	}
+
+	if (do_setuid && seteuid(job->uid) < 0) {
+		error("seteuid: %m");
+		return -1;
+	}
+
+	return SLURM_SUCCESS;
+}
+
+static int
+_reclaim_privileges(struct priv_state *ps)
+{
+	int rc = SLURM_SUCCESS;
+
+	/*
+	 * No need to reclaim privileges if our uid == job->uid
+	 */
+	if (geteuid() == ps->saved_uid)
+		goto done;
+	else if (seteuid(ps->saved_uid) < 0) {
+		error("seteuid: %m");
+		rc = -1;
+	} else if (setegid(ps->saved_gid) < 0) {
+		error("setegid: %m");
+		rc = -1;
+	} else if (setgroups(ps->ngids, ps->gid_list) < 0) {
+		error("setgroups: %m");
+		rc = -1;
+	}
+
+done:
+	xfree(ps->gid_list);
+
+	return rc;
+}
+
 static void _reset_slurm_profile_conf(void)
 {
 	xfree(hdf5_conf.dir);
@@ -303,7 +394,7 @@ extern void acct_gather_profile_p_get(enum acct_gather_profile_info info_type,
 extern int acct_gather_profile_p_node_step_start(stepd_step_rec_t* job)
 {
 	int rc = SLURM_SUCCESS;
-
+	struct priv_state sprivs = { 0 };
 	char *profile_file_name;
 
 	xassert(running_in_slurmstepd());
@@ -346,11 +437,24 @@ extern int acct_gather_profile_p_node_step_start(stepd_step_rec_t* job)
 		 acct_gather_profile_to_string(g_profile_running),
 		 profile_file_name);
 
+	if (_drop_privileges(g_job, true, &sprivs, false) < 0) {
+		error("%s: Unable to drop privileges", __func__);
+		xfree(profile_file_name);
+		return SLURM_ERROR;
+	}
+
 	/*
 	 * Create a new file using the default properties
 	 */
 	file_id = H5Fcreate(profile_file_name, H5F_ACC_TRUNC, H5P_DEFAULT,
 			    H5P_DEFAULT);
+
+	if (_reclaim_privileges(&sprivs) < 0) {
+		error("%s: Unable to reclaim privileges", __func__);
+		xfree(profile_file_name);
+		return SLURM_ERROR;
+	}
+
 	if (chown(profile_file_name, (uid_t)g_job->uid,
 		  (gid_t)g_job->gid) < 0)
 		error("chown(%s): %m", profile_file_name);
