Change in libosmocore[master]: exec: Introduce osmo_system_nowait2() to allow specify a user

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

laforge gerrit-no-reply at lists.osmocom.org
Sat Apr 18 19:10:21 UTC 2020


laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/17852 )

Change subject: exec: Introduce osmo_system_nowait2() to allow specify a user
......................................................................

exec: Introduce osmo_system_nowait2() to allow specify a user

For a process running as root, it may be desirable to drop privileges
down to a normal user  before executing an external command.  Let's
add a new API function for that.

Change-Id: If1431f930f72a8d6c1d102426874a11b7a2debd9
---
M include/osmocom/core/exec.h
M src/exec.c
2 files changed, 49 insertions(+), 2 deletions(-)

Approvals:
  Jenkins Builder: Verified
  pespin: Looks good to me, but someone else must approve
  laforge: Looks good to me, approved



diff --git a/include/osmocom/core/exec.h b/include/osmocom/core/exec.h
index 6bbd352..e63ec11 100644
--- a/include/osmocom/core/exec.h
+++ b/include/osmocom/core/exec.h
@@ -25,4 +25,5 @@
 int osmo_environment_filter(char **out, size_t out_len, char **in, const char **whitelist);
 int osmo_environment_append(char **out, size_t out_len, char **in);
 int osmo_close_all_fds_above(int last_fd_to_keep);
+int osmo_system_nowait2(const char *command, const char **env_whitelist, char **addl_env, const char *user);
 int osmo_system_nowait(const char *command, const char **env_whitelist, char **addl_env);
diff --git a/src/exec.c b/src/exec.c
index 62f5919..578e2b1 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -23,6 +23,7 @@
 #include "config.h"
 #ifndef EMBEDDED
 
+#define _GNU_SOURCE
 #include <unistd.h>
 
 #include <errno.h>
@@ -31,6 +32,7 @@
 #include <stdio.h>
 #include <dirent.h>
 #include <sys/types.h>
+#include <pwd.h>
 
 #include <osmocom/core/logging.h>
 #include <osmocom/core/utils.h>
@@ -192,23 +194,34 @@
 /* Seems like POSIX has no header file for this, and even glibc + __USE_GNU doesn't help */
 extern char **environ;
 
-/*! call an external shell command without waiting for it.
+/*! call an external shell command as 'user' without waiting for it.
  *
  *  This mimics the behavior of system(3), with the following differences:
  *  - it doesn't wait for completion of the child process
  *  - it closes all non-stdio file descriptors by iterating /proc/self/fd
  *  - it constructs a reduced environment where only whitelisted keys survive
  *  - it (optionally) appends additional variables to the environment
+ *  - it (optionally) changes the user ID to that of 'user' (requires execution as root)
  *
  *  \param[in] command the shell command to be executed, see system(3)
  *  \param[in] env_whitelist A white-list of keys for environment variables
  *  \param[in] addl_env any additional environment variables to be appended
+ *  \param[in] user name of the user to which we should switch before executing the command
  *  \returns PID of generated child process; negative on error
  */
-int osmo_system_nowait(const char *command, const char **env_whitelist, char **addl_env)
+int osmo_system_nowait2(const char *command, const char **env_whitelist, char **addl_env, const char *user)
 {
+	struct passwd _pw, *pw;
+	int getpw_buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
 	int rc;
 
+	if (user) {
+		char buf[getpw_buflen];
+		getpwnam_r(user, &_pw, buf, sizeof(buf), &pw);
+		if (!pw)
+			return -EINVAL;
+	}
+
 	rc = fork();
 	if (rc == 0) {
 		/* we are in the child */
@@ -232,6 +245,20 @@
 				return rc;
 		}
 
+		/* drop privileges */
+		if (pw) {
+			if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0) {
+				perror("setresgid() during privilege drop");
+				exit(1);
+			}
+
+			if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) {
+				perror("setresuid() during privilege drop");
+				exit(1);
+			}
+
+		}
+
 		/* if we want to behave like system(3), we must go via the shell */
 		execle("/bin/sh", "sh", "-c", command, (char *) NULL, new_env);
 		/* only reached in case of error */
@@ -244,4 +271,23 @@
 	}
 }
 
+/*! call an external shell command without waiting for it.
+ *
+ *  This mimics the behavior of system(3), with the following differences:
+ *  - it doesn't wait for completion of the child process
+ *  - it closes all non-stdio file descriptors by iterating /proc/self/fd
+ *  - it constructs a reduced environment where only whitelisted keys survive
+ *  - it (optionally) appends additional variables to the environment
+ *
+ *  \param[in] command the shell command to be executed, see system(3)
+ *  \param[in] env_whitelist A white-list of keys for environment variables
+ *  \param[in] addl_env any additional environment variables to be appended
+ *  \returns PID of generated child process; negative on error
+ */
+int osmo_system_nowait(const char *command, const char **env_whitelist, char **addl_env)
+{
+	return osmo_system_nowait2(command, env_whitelist, addl_env, NULL);
+}
+
+
 #endif /* EMBEDDED */

-- 
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/17852
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: If1431f930f72a8d6c1d102426874a11b7a2debd9
Gerrit-Change-Number: 17852
Gerrit-PatchSet: 2
Gerrit-Owner: laforge <laforge at osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-CC: fixeria <axilirator at gmail.com>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20200418/9031e967/attachment.htm>


More information about the gerrit-log mailing list