From b714ba15c24412b135b93c236c124100a911c4c7 Mon Sep 17 00:00:00 2001 From: iris Date: Sun, 31 May 2026 11:24:23 +0200 Subject: [PATCH] harness: drop trailing /bin from systemd path entries so wrapper sudo resolves (#672 fixup) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit systemd.services..path appends /bin to each entry, so the literal '/run/wrappers/bin' here was being expanded to '/run/wrappers/bin/bin' inside the unit's PATH — a path that doesn't exist. 'which sudo' then fell back to '/run/current-system/sw/bin/sudo' (the non-setuid nix-store binary) and refused with 'must be owned by uid 0 and have the setuid bit set' on every agent, despite hyperhive.user.passwordlessSudo = true. Verified on this container post-rebuild: PATH includes /run/wrappers/bin/bin (non-existent) /run/wrappers/bin/sudo exists with mode r-s--x--x (real setuid) but `sudo` resolves to /run/current-system/sw/bin/sudo and fails. Fix: drop the trailing /bin from both entries. systemd appends it. The /run/current-system/sw entry was already correctly expanding to /run/current-system/sw/bin (because of the same auto-append), which is why everything else on PATH worked despite the broken wrappers entry — only sudo (the one binary that needs the wrapper dir) was affected. --- nix/templates/harness-base.nix | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/nix/templates/harness-base.nix b/nix/templates/harness-base.nix index d99061ff..b8ac71bb 100644 --- a/nix/templates/harness-base.nix +++ b/nix/templates/harness-base.nix @@ -1269,8 +1269,17 @@ in # `hyperhive.user.passwordlessSudo = true` is configured # (#672 fixup pulled forward into this PR to avoid the # regression argus flagged on #676). + # + # `systemd.services..path` appends `/bin` to each entry, + # so the bare prefixes here resolve to `/run/wrappers/bin` + + # `/run/current-system/sw/bin` inside the unit's PATH. Passing + # the trailing `/bin` ourselves (the natural-looking spelling) + # would yield `/run/wrappers/bin/bin` + `/run/current-system/sw/bin/bin`, + # neither of which exists — that's how #672 originally landed + # broken: every agent had a PATH pointing at non-existent dirs + # and `which sudo` kept falling back to the un-setuid binary. path = [ - "/run/wrappers/bin" + "/run/wrappers" "/run/current-system/sw" ]; environment = {