From 62bf37d48109480315bf84e6d13e9d8fbf390619 Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Sun, 22 Feb 2026 16:56:45 -0600 Subject: [PATCH] fix: bind-mount greywall binary for Landlock wrapper re-execution The Landlock wrapper re-executes the greywall binary inside the sandbox with --landlock-apply. When greywall is run from a path outside the CWD (e.g., ~/bin/greywall from /home/user/project), the binary doesn't exist inside the sandbox because only system paths and CWD are mounted. This adds a --ro-bind for the greywall executable so the wrapper always works regardless of where the binary is located. --- internal/sandbox/linux.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/sandbox/linux.go b/internal/sandbox/linux.go index 3db289d..9306421 100644 --- a/internal/sandbox/linux.go +++ b/internal/sandbox/linux.go @@ -976,6 +976,14 @@ func WrapCommandLinuxWithOptions(cfg *config.Config, command string, proxyBridge fmt.Fprintf(os.Stderr, "[greywall:linux] Skipping Landlock wrapper (running as library, not greywall CLI)\n") } + // Bind-mount the greywall binary into the sandbox so the Landlock wrapper + // can re-execute it. Without this, running greywall from a directory that + // isn't the CWD (e.g., ~/bin/greywall from /home/user/project) would fail + // because the binary path doesn't exist inside the sandbox. + if useLandlockWrapper && greywallExePath != "" { + bwrapArgs = append(bwrapArgs, "--ro-bind", greywallExePath, greywallExePath) + } + bwrapArgs = append(bwrapArgs, "--", shellPath, "-c") // Build the inner command that sets up tun2socks and runs the user command