about summary refs log tree commit diff
path: root/src/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/util.cc15
-rw-r--r--src/libutil/util.hh5
2 files changed, 16 insertions, 4 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 0f4d3d92b866..55b9144f314e 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -16,6 +16,7 @@
 #include <future>
 
 #include <fcntl.h>
+#include <grp.h>
 #include <limits.h>
 #include <pwd.h>
 #include <sys/ioctl.h>
@@ -914,8 +915,8 @@ void killUser(uid_t uid)
 
 /* Wrapper around vfork to prevent the child process from clobbering
    the caller's stack frame in the parent. */
-pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline));
-pid_t doFork(bool allowVfork, std::function<void()> fun)
+static pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline));
+static pid_t doFork(bool allowVfork, std::function<void()> fun)
 {
 #ifdef __linux__
     pid_t pid = allowVfork ? vfork() : fork();
@@ -1025,6 +1026,16 @@ void runProgram2(const RunOptions & options)
         if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1)
             throw SysError("dupping stdin");
 
+        //if (options.chdir && chdir((*options.chdir).c_str()) == -1)
+        //    throw SysError("chdir failed");
+        if (options.gid && setgid(*options.gid) == -1)
+            throw SysError("setgid failed");
+        /* Drop all other groups if we're setgid. */
+        if (options.gid && setgroups(0, 0) == -1)
+            throw SysError("setgroups failed");
+        if (options.uid && setuid(*options.uid) == -1)
+            throw SysError("setuid failed");
+
         Strings args_(options.args);
         args_.push_front(options.program);
 
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 824a35b987e8..7c57d0afad98 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -265,10 +265,11 @@ string runProgram(Path program, bool searchPath = false,
     const Strings & args = Strings(),
     const std::optional<std::string> & input = {});
 
-pid_t doFork(bool allowVfork, std::function<void()> fun);
-
 struct RunOptions
 {
+    std::optional<uid_t> uid;
+    std::optional<uid_t> gid;
+    std::optional<Path> chdir;
     Path program;
     bool searchPath = true;
     Strings args;