diff --git a/lix/libexec/meson.build b/lix/libexec/meson.build index 8c458a51b..30e54d922 100644 --- a/lix/libexec/meson.build +++ b/lix/libexec/meson.build @@ -14,6 +14,13 @@ kill_user = executable( install_dir : libexecdir / 'lix', ) +run_diff_hook = executable( + 'run-diff-hook', + files('run-diff-hook.cc'), + install : true, + install_dir : libexecdir / 'lix', +) + run_pager = executable( 'run-pager', files('run-pager.cc'), diff --git a/lix/libexec/run-diff-hook.cc b/lix/libexec/run-diff-hook.cc new file mode 100644 index 000000000..b39721ab2 --- /dev/null +++ b/lix/libexec/run-diff-hook.cc @@ -0,0 +1,27 @@ +#include "common.hh" + +#include + +using std::literals::operator""sv; + +LIBEXEC_HELPER(3) + +int helperMain(const char * name, std::span args) noexcept +{ + const auto uid = args[0]; + const auto gid = args[1]; + const auto hook = args.subspan(2); + + DIE_UNLESS_SYS("chdir", chdir("/")); + if (gid != "-"sv) { + DIE_UNLESS_SYS("setgid", setgid(argToInt("gid", gid))); + /* Drop all other groups if we're setgid. */ + DIE_UNLESS_SYS("setgroups", setgroups(0, 0)); + } + if (uid != "-"sv) { + DIE_UNLESS_SYS("setuid", setuid(argToInt("uid", uid))); + } + + execvp(hook[0], hook.data()); + die("exec failed"); +} diff --git a/lix/libstore/build/local-derivation-goal.cc b/lix/libstore/build/local-derivation-goal.cc index db3da2c0a..dcf47e5c4 100644 --- a/lix/libstore/build/local-derivation-goal.cc +++ b/lix/libstore/build/local-derivation-goal.cc @@ -18,6 +18,7 @@ #include "lix/libutil/regex.hh" #include "lix/libutil/file-descriptor.hh" #include "lix/libutil/file-system.hh" +#include "lix/libutil/processes.hh" #include "lix/libutil/result.hh" #include "lix/libutil/topo-sort.hh" #include "lix/libutil/json.hh" @@ -41,6 +42,7 @@ #include #include +#include #include #include #include @@ -84,23 +86,24 @@ try { if (diffHookOpt && settings.runDiffHook) { auto & diffHook = *diffHookOpt; try { - auto diffRes = TRY_AWAIT(runProgram(RunOptions{ - .program = diffHook, - .searchPath = true, - .args = {tryA, tryB, drvPath, tmpDir}, - .uid = uid, - .gid = gid, - .chdir = "/" - })); - if (!statusOk(diffRes.first)) - throw ExecError(diffRes.first, - "diff-hook program '%1%' %2%", - diffHook, - statusToString(diffRes.first)); - - if (diffRes.second != "") { - printError("%1%", Uncolored(chomp(diffRes.second))); - } + auto hook = runHelper( + "run-diff-hook", + { + .args = + {uid ? std::to_string(*uid) : "-", + gid ? std::to_string(*gid) : "-", + diffHook, + tryA, + tryB, + drvPath, + tmpDir}, + .captureStdout = true, + } + ); + auto diffRes = TRY_AWAIT(hook.getStdout()->drain()); + hook.waitAndCheck(); + if (diffRes != "") + printError("%1%", Uncolored(chomp(diffRes))); } catch (Error & error) { ErrorInfo ei = error.info(); // FIXME: wrap errors.