aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGraham Christensen <graham@grahamc.com>2019-05-11 16:35:53 -0400
committerGraham Christensen <graham@grahamc.com>2019-05-12 13:17:27 -0400
commitb4a05edbfe49f87555fd284dfb0d6c56ed43217d (patch)
tree447fd9d1be15f15f1cb0c8020b63b95acb74933b /src
parentdde8eeb39ae9fb73011462c74e5fa6405e432147 (diff)
runProgram: support gid, uid, chdir
Diffstat (limited to 'src')
-rw-r--r--src/libstore/build.cc36
-rw-r--r--src/libutil/util.cc15
-rw-r--r--src/libutil/util.hh5
3 files changed, 32 insertions, 24 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 8397cd0d1..8902e22bd 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -465,26 +465,22 @@ void handleDiffHook(bool allowVfork, uid_t uid, uid_t gid, Path tryA, Path tryB,
{
auto diffHook = settings.diffHook;
if (diffHook != "" && settings.runDiffHook) {
- auto wrapper = [&]() {
- if (chdir("/") == -1)
- throw SysError("chdir / failed");
- if (setgid(gid) == -1)
- throw SysError("setgid failed");
- if (setgroups(0, 0) == -1)
- throw SysError("setgroups failed");
- if (setuid(uid) == -1)
- throw SysError("setuid failed");
-
- try {
- auto diff = runProgram(diffHook, true, {tryA, tryB, drvPath, tmpDir});
- if (diff != "")
- printError(chomp(diff));
- } catch (Error & error) {
- printError("diff hook execution failed: %s", error.what());
- }
- };
-
- doFork(allowVfork, wrapper);
+ try {
+ RunOptions diffHookOptions(diffHook,{tryA, tryB, drvPath, tmpDir});
+ diffHookOptions.searchPath = true;
+ diffHookOptions.uid = uid;
+ diffHookOptions.gid = gid;
+ diffHookOptions.chdir = "/";
+
+ auto diffRes = runProgram(diffHookOptions);
+ if (!statusOk(diffRes.first))
+ throw ExecError(diffRes.first, fmt("diff-hook program '%1%' %2%", diffHook, statusToString(diffRes.first)));
+
+ if (diffRes.second != "")
+ printError(chomp(diffRes.second));
+ } catch (Error & error) {
+ printError("diff hook execution failed: %s", error.what());
+ }
}
}
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 0f4d3d92b..55b9144f3 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 824a35b98..7c57d0afa 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;