libstore: add a diff hook helper libexec binary

diff hooks use uid/gid switch functionality that is otherwise only
needed for linux sandbox setup and unsupported by posix_spawn. not
doing these switches inside lix core code may let us move to using
posix_spawn for most process launching in the future, and for diff
hooks the added overhead of a wrapper program really does not hurt
at all. diff hooks are expected to be expensive in terms of output
size, process launch overhead is not likely to even be noticeable.

Change-Id: Ifa4b3eedef237632db3eb88d10e6469acae01f9e
This commit is contained in:
eldritch horrors
2026-01-22 15:23:38 +00:00
parent d7b0d322f7
commit 5351518c75
3 changed files with 54 additions and 17 deletions
+7
View File
@@ -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'),
+27
View File
@@ -0,0 +1,27 @@
#include "common.hh"
#include <grp.h>
using std::literals::operator""sv;
LIBEXEC_HELPER(3)
int helperMain(const char * name, std::span<char *> 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_t>("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_t>("uid", uid)));
}
execvp(hook[0], hook.data());
die("exec failed");
}
+20 -17
View File
@@ -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 <stdexcept>
#include <sys/stat.h>
#include <string>
#include <sys/un.h>
#include <fcntl.h>
#include <termios.h>
@@ -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.