diff --git a/modules/programs/make-sandboxed.nix b/modules/programs/make-sandboxed.nix index 4e1c36365..c576274a9 100644 --- a/modules/programs/make-sandboxed.nix +++ b/modules/programs/make-sandboxed.nix @@ -6,7 +6,8 @@ gnugrep, gnused, linkFarm, - makeWrapper, + makeBinaryWrapper, + makeShellWrapper, runCommandLocal, sanebox, writeShellScriptBin, @@ -59,7 +60,8 @@ let # so that the unwrapped's take precendence and we limit interference (e.g. makeWrapper impl) fakeSaneSandboxed gnugrep - makeWrapper + makeBinaryWrapper + makeShellWrapper ] ++ (unwrapped.nativeBuildInputs or []); disallowedReferences = (unwrapped.disallowedReferences or []) ++ [ # the fake sandbox gates itself behind SANEBOX_DISABLE, so if it did end up deployed @@ -71,14 +73,14 @@ let assertExecutable() { : # my programs refer to sanebox by name, not path, which triggers an over-eager assertion in nixpkgs (so, mask that) } - # makeDocumentedCWrapper() { - # # this is identical to nixpkgs' implementation, only replace execv with execvp, the latter which looks for the executable on PATH. - # local src=$(makeCWrapper "$@") - # src="''${src/return execv(/return execvp(}" - # local docs=$(docstring "$@") - # printf '%s\n\n' "$src" - # printf '%s\n' "$docs" - # } + makeDocumentedCWrapper() { + # this is identical to nixpkgs' implementation, only replace execv with execvp, the latter which looks for the executable on PATH. + local src=$(makeCWrapper "$@") + src="''${src/return execv(/return execvp(}" + local docs=$(docstring "$@") + printf '%s\n\n' "$src" + printf '%s\n' "$docs" + } sandboxWrap() { local _dir="$1" @@ -99,18 +101,26 @@ let mv "$_dir/$_name" "$_dir/.sandboxed/" fi - # N.B.: double `escapeShellArg`: once for the shell wrapper, and again for runtime because the shell wrapper doesn't escape. - # spotcheck this by seeing if animatch (requires a path "Holy Pangolin") works - makeShellWrapper ${sanebox'} "$_dir/$_name" --suffix PATH : /run/current-system/sw/libexec/${sanebox.pname} \ - --inherit-argv0 \ - ${lib.escapeShellArgs (lib.flatten (builtins.map (f: [ "--add-flags" (lib.escapeShellArg f) ]) extraSandboxArgs))} \ - --add-flags "$_dir/.sandboxed/$_name" - if [ -n "${sanebox.interpreter or ""}" ]; then + # N.B.: double `escapeShellArg`: once for the shell wrapper, and again for runtime because the shell wrapper doesn't escape. + # spotcheck this by seeing if animatch (requires a path "Holy Pangolin") works + makeShellWrapper ${sanebox'} "$_dir/$_name" \ + --suffix PATH : /run/current-system/sw/libexec/${sanebox.pname} \ + --inherit-argv0 \ + ${lib.escapeShellArgs (lib.flatten (builtins.map (f: [ "--add-flags" (lib.escapeShellArg f) ]) extraSandboxArgs))} \ + --add-flags "$_dir/.sandboxed/$_name" + # `exec`ing a script with an interpreter will smash $0. instead, source it to preserve $0: # - substituteInPlace "$_dir/$_name" \ --replace-fail 'exec -a "$0" ' 'source ' + else + # we can use a binary shell wrapper since the wrapper's environment is capable of forwarding argv[0]. + makeBinaryWrapper ${sanebox'} "$_dir/$_name" \ + --suffix PATH : /run/current-system/sw/libexec/${sanebox.pname} \ + --inherit-argv0 \ + ${lib.escapeShellArgs (lib.flatten (builtins.map (f: [ "--add-flags" f ]) extraSandboxArgs))} \ + --add-flags "$_dir/.sandboxed/$_name" fi } @@ -406,6 +416,8 @@ let local dir="$1" local binname="$2" echo "checking if $dir/$binname is sandboxed" + echo " sandboxer is ${sanebox.name}" + echo " PATH=$PATH" # XXX: call by full path because some binaries (e.g. util-linux) would otherwise # be shadowed by things the nix builder implicitly puts on PATH. # additionally, call via qemu and manually specify the interpreter *if the file has one*. @@ -457,7 +469,7 @@ let }; }); - make-sandboxed = { pkgName, package, wrapperType, embedSandboxer ? false, extraSandboxerArgs ? [], passthru ? {} }@args: + make-sandboxed = { pkgName, package, wrapperType, embedSandboxer ? false, extraSandboxerArgs ? [], passthru ? {} }: let unsandboxed = package; sanebox' = if embedSandboxer then