sane-sandboxed -> sanebox

This commit is contained in:
2024-05-15 01:41:40 +00:00
parent f9a6873ee9
commit adfaa7f9c1
21 changed files with 131 additions and 131 deletions

View File

@@ -61,7 +61,7 @@
- <https://github.com/flatpak/xdg-dbus-proxy> - <https://github.com/flatpak/xdg-dbus-proxy>
- remove `.ssh` access from Firefox! - remove `.ssh` access from Firefox!
- limit access to `~/knowledge/secrets` through an agent that requires GUI approval, so a firefox exploit can't steal all my logins - limit access to `~/knowledge/secrets` through an agent that requires GUI approval, so a firefox exploit can't steal all my logins
- port sane-sandboxed to a compiled language (hare?) - port sanebox to a compiled language (hare?)
- it adds like 50-70ms launch time _on my laptop_. i'd hate to know how much that is on the pinephone. - it adds like 50-70ms launch time _on my laptop_. i'd hate to know how much that is on the pinephone.
- remove /run/wrappers from the sandbox path - remove /run/wrappers from the sandbox path
- they're mostly useless when using no-new-privs, just an opportunity to forget to specify deps - they're mostly useless when using no-new-privs, just an opportunity to forget to specify deps

View File

@@ -389,7 +389,7 @@ in
forkstat.sandbox.method = "landlock"; #< doesn't seem to support bwrap forkstat.sandbox.method = "landlock"; #< doesn't seem to support bwrap
forkstat.sandbox.extraConfig = [ forkstat.sandbox.extraConfig = [
"--sane-sandbox-keep-namespace" "pid" "--sanebox-keep-namespace" "pid"
]; ];
forkstat.sandbox.extraPaths = [ forkstat.sandbox.extraPaths = [
"/proc" "/proc"
@@ -744,7 +744,7 @@ in
# procps: free, pgrep, pidof, pkill, ps, pwait, top, uptime, couple others # procps: free, pgrep, pidof, pkill, ps, pwait, top, uptime, couple others
procps.sandbox.method = "bwrap"; procps.sandbox.method = "bwrap";
procps.sandbox.extraConfig = [ procps.sandbox.extraConfig = [
"--sane-sandbox-keep-namespace" "pid" "--sanebox-keep-namespace" "pid"
]; ];
pstree.sandbox.method = "landlock"; pstree.sandbox.method = "landlock";

View File

@@ -42,7 +42,7 @@ in
sandbox.extraConfig = [ sandbox.extraConfig = [
# else it fails to reap its children (or, maybe, it fails to hook its parent's death signal?) # else it fails to reap its children (or, maybe, it fails to hook its parent's death signal?)
# might be possible to remove this, but kinda hard to see a clean way. # might be possible to remove this, but kinda hard to see a clean way.
"--sane-sandbox-keep-namespace" "pid" "--sanebox-keep-namespace" "pid"
]; ];
suggestedPrograms = [ "blast-ugjka" "sane-die-with-parent" ]; suggestedPrograms = [ "blast-ugjka" "sane-die-with-parent" ];
}; };

View File

@@ -103,9 +103,9 @@
./s6-rc.nix ./s6-rc.nix
./sane-input-handler ./sane-input-handler
./sane-open.nix ./sane-open.nix
./sane-sandboxed.nix
./sane-screenshot.nix ./sane-screenshot.nix
./sane-scripts.nix ./sane-scripts.nix
./sanebox.nix
./schlock.nix ./schlock.nix
./sfeed.nix ./sfeed.nix
./signal-desktop.nix ./signal-desktop.nix

View File

@@ -48,7 +48,7 @@
sandbox.extraConfig = [ sandbox.extraConfig = [
# XXX(2024/04/21): without this it fails to convert .dng -> .jpg. # XXX(2024/04/21): without this it fails to convert .dng -> .jpg.
# "bwrap: open /proc/34/ns/ns failed: No such file or directory" # "bwrap: open /proc/34/ns/ns failed: No such file or directory"
"--sane-sandbox-keep-namespace" "pid" "--sanebox-keep-namespace" "pid"
]; ];
suggestedPrograms = [ "dconf" ]; #< not sure if necessary suggestedPrograms = [ "dconf" ]; #< not sure if necessary

View File

@@ -61,7 +61,7 @@ in
# ]; # ];
sandbox.wrapperType = "inplace"; #< its config files refer to its binaries by full path sandbox.wrapperType = "inplace"; #< its config files refer to its binaries by full path
sandbox.extraConfig = [ sandbox.extraConfig = [
"--sane-sandbox-keep-namespace" "pid" "--sanebox-keep-namespace" "pid"
]; ];
sandbox.capabilities = [ sandbox.capabilities = [
# if rtkit isn't present, and sandboxing is via landlock, these capabilities allow pipewire to claim higher scheduling priority # if rtkit isn't present, and sandboxing is via landlock, these capabilities allow pipewire to claim higher scheduling priority

View File

@@ -113,7 +113,7 @@ in
"/mnt/servo/playground" "/mnt/servo/playground"
]; ];
sandbox.extraConfig = [ sandbox.extraConfig = [
"--sane-sandbox-keep-namespace" "pid" # for sane-open to toggle keyboard "--sanebox-keep-namespace" "pid" # for sane-open to toggle keyboard
]; ];
fs.".config/rofi/config.rasi".symlink.target = ./config.rasi; fs.".config/rofi/config.rasi".symlink.target = ./config.rasi;

View File

@@ -113,7 +113,7 @@ in
sandbox.whitelistDbus = [ "user" ]; #< to launch applications sandbox.whitelistDbus = [ "user" ]; #< to launch applications
sandbox.extraRuntimePaths = [ "sway" ]; sandbox.extraRuntimePaths = [ "sway" ];
sandbox.extraConfig = [ sandbox.extraConfig = [
"--sane-sandbox-keep-namespace" "pid" "--sanebox-keep-namespace" "pid"
]; ];
}; };

View File

@@ -5,7 +5,7 @@
sandbox.autodetectCliPaths = "existing"; # for when opening a file sandbox.autodetectCliPaths = "existing"; # for when opening a file
sandbox.whitelistDbus = [ "user" ]; sandbox.whitelistDbus = [ "user" ];
sandbox.extraConfig = [ sandbox.extraConfig = [
"--sane-sandbox-keep-namespace" "pid" # to toggle keyboard "--sanebox-keep-namespace" "pid" # to toggle keyboard
]; ];
sandbox.extraHomePaths = [ sandbox.extraHomePaths = [
".local/share/applications" ".local/share/applications"

View File

@@ -3,8 +3,8 @@ let
cfg = config.sane.programs; cfg = config.sane.programs;
in in
{ {
sane.programs.sane-sandboxed = { sane.programs.sanebox = {
packageUnwrapped = pkgs.sane-sandboxed.override { packageUnwrapped = pkgs.sanebox.override {
bubblewrap = cfg.bubblewrap.package; bubblewrap = cfg.bubblewrap.package;
firejail = cfg.firejail.package; firejail = cfg.firejail.package;
landlock-sandboxer = pkgs.landlock-sandboxer.override { landlock-sandboxer = pkgs.landlock-sandboxer.override {

View File

@@ -245,7 +245,7 @@ exec --no-startup-id mv $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY.lock $XDG_RUNTIME_DIR/
set $$WAYLAND_DISPLAY "$(echo $DESIRED_WAYLAND_DISPLAY)" set $$WAYLAND_DISPLAY "$(echo $DESIRED_WAYLAND_DISPLAY)"
# manually export PATH here, since all my user services need that, and sane-sandboxed implementation depends on it. # manually export PATH here, since all my user services need that, and sanebox implementation depends on it.
# also, manually export XDG_DATA_DIRS. glib fails in weird ways (e.g. thinks everything is application/x-octet-stream mime type) without it. # also, manually export XDG_DATA_DIRS. glib fails in weird ways (e.g. thinks everything is application/x-octet-stream mime type) without it.
# for more, see: <repo:nixos/nixpkgs:nixos/modules/programs/wayland/sway.nix> # for more, see: <repo:nixos/nixpkgs:nixos/modules/programs/wayland/sway.nix>
# #

View File

@@ -109,7 +109,7 @@ in
]; ];
sandbox.extraConfig = [ sandbox.extraConfig = [
# systemctl calls seem to require same pid namespace # systemctl calls seem to require same pid namespace
"--sane-sandbox-keep-namespace" "pid" "--sanebox-keep-namespace" "pid"
]; ];
# glib/gio applications support many notification backends ("portal", "gtk", "freedesktop", ...). # glib/gio applications support many notification backends ("portal", "gtk", "freedesktop", ...).

View File

@@ -136,10 +136,10 @@ in
serviceConfig.ExecStart = "${pkgs.util-linux}/bin/agetty --login-program '${cfg.config.launcher}/bin/unl0kr-login' --noclear --skip-login --keep-baud ${tty} 115200,38400,9600 $TERM"; serviceConfig.ExecStart = "${pkgs.util-linux}/bin/agetty --login-program '${cfg.config.launcher}/bin/unl0kr-login' --noclear --skip-login --keep-baud ${tty} 115200,38400,9600 $TERM";
path = [ path = [
# necessary for `sane-sandboxed` to be found. TODO: add this to every systemd service. # necessary for `sanebox` to be found. TODO: add this to every systemd service.
"/run/current-system/sw" # `/bin` is appended "/run/current-system/sw" # `/bin` is appended
]; ];
# needed to find sane-sandbox profiles (TODO: add this to every service) # needed to find sanebox profiles (TODO: add this to every service)
environment.XDG_DATA_DIRS = "/run/current-system/sw/share"; environment.XDG_DATA_DIRS = "/run/current-system/sw/share";
serviceConfig.Type = "simple"; serviceConfig.Type = "simple";

View File

@@ -22,7 +22,7 @@
]; ];
# sandbox.extraConfig = [ # sandbox.extraConfig = [
# # needed if i want rtkit to grant this higher scheduling priority # # needed if i want rtkit to grant this higher scheduling priority
# "--sane-sandbox-keep-namespace" "pid" # "--sanebox-keep-namespace" "pid"
# ]; # ];
suggestedPrograms = [ "alsa-ucm-conf" ]; suggestedPrograms = [ "alsa-ucm-conf" ];

View File

@@ -41,7 +41,7 @@ let
else else
let let
makeProfile = pkgs.callPackage ./make-sandbox-profile.nix { }; makeProfile = pkgs.callPackage ./make-sandbox-profile.nix { };
makeSandboxed = pkgs.callPackage ./make-sandboxed.nix { sane-sandboxed = config.sane.programs.sane-sandboxed.package; }; makeSandboxed = pkgs.callPackage ./make-sandboxed.nix { sanebox = config.sane.programs.sanebox.package; };
# derefSymlinks: [ str ] -> [ str ]: for each path which is a symlink (or a child of a symlink'd dir), dereference one layer of symlink. else, return the path unchanged. # derefSymlinks: [ str ] -> [ str ]: for each path which is a symlink (or a child of a symlink'd dir), dereference one layer of symlink. else, return the path unchanged.
derefSymlinks = paths: builtins.map (fs-lib.derefSymlink config.sane.fs) paths; derefSymlinks = paths: builtins.map (fs-lib.derefSymlink config.sane.fs) paths;
@@ -159,7 +159,7 @@ let
# useful to iterate a package's sandbox config without redeploying. # useful to iterate a package's sandbox config without redeploying.
embedSandboxer = true; embedSandboxer = true;
extraSandboxerArgs = [ extraSandboxerArgs = [
"--sane-sandbox-profile-dir" "${defaultProfile}/share/sane-sandboxed/profiles" "--sanebox-profile-dir" "${defaultProfile}/share/sanebox/profiles"
]; ];
}); });
withEmbeddedSandboxerOnly = makeSandboxed (makeSandboxedArgs // { withEmbeddedSandboxerOnly = makeSandboxed (makeSandboxedArgs // {
@@ -466,9 +466,9 @@ let
description = '' description = ''
extra arguments to pass to the sandbox wrapper. extra arguments to pass to the sandbox wrapper.
example: [ example: [
"--sane-sandbox-firejail-arg" "--sanebox-firejail-arg"
"--whitelist=''${HOME}/.ssh" "--whitelist=''${HOME}/.ssh"
"--sane-sandbox-firejail-arg" "--sanebox-firejail-arg"
"--keep-dev-shm" "--keep-dev-shm"
] ]
''; '';
@@ -530,7 +530,7 @@ let
++ lib.optionals config.sandbox.whitelistS6 [ "s6" ] # TODO: this allows re-writing the services themselves: don't allow that! ++ lib.optionals config.sandbox.whitelistS6 [ "s6" ] # TODO: this allows re-writing the services themselves: don't allow that!
; ;
sandbox.extraConfig = lib.mkIf config.sandbox.usePortal [ sandbox.extraConfig = lib.mkIf config.sandbox.usePortal [
"--sane-sandbox-portal" "--sanebox-portal"
]; ];
}; };
}); });
@@ -666,8 +666,8 @@ in
in lib.mkMerge [ in lib.mkMerge [
(take (sane-lib.mkTypedMerge take configs)) (take (sane-lib.mkTypedMerge take configs))
{ {
environment.pathsToLink = [ "/share/sane-sandboxed" ]; environment.pathsToLink = [ "/share/sanebox" ];
sane.programs.sane-sandboxed.enableFor.system = true; sane.programs.sanebox.enableFor.system = true;
# expose the pkgs -- as available to the system -- as a build target. # expose the pkgs -- as available to the system -- as a build target.
system.build.pkgs = pkgs; system.build.pkgs = pkgs;
} }

View File

@@ -14,44 +14,44 @@
}: }:
let let
allowPath = p: [ allowPath = p: [
"--sane-sandbox-path" "--sanebox-path"
p p
]; ];
allowPaths = paths: lib.flatten (builtins.map allowPath paths); allowPaths = paths: lib.flatten (builtins.map allowPath paths);
cacheLink = from: to: [ cacheLink = from: to: [
"--sane-sandbox-cache-symlink" "--sanebox-cache-symlink"
from from
to to
]; ];
cacheLinks = links: lib.flatten (lib.mapAttrsToList cacheLink links); cacheLinks = links: lib.flatten (lib.mapAttrsToList cacheLink links);
capabilityFlags = lib.flatten (builtins.map (c: [ "--sane-sandbox-cap" c ]) capabilities); capabilityFlags = lib.flatten (builtins.map (c: [ "--sanebox-cap" c ]) capabilities);
netItems = lib.optionals (netDev != null) [ netItems = lib.optionals (netDev != null) [
"--sane-sandbox-net" "--sanebox-net"
netDev netDev
] ++ lib.optionals (dns != null) ( ] ++ lib.optionals (dns != null) (
lib.flatten (builtins.map lib.flatten (builtins.map
(addr: [ "--sane-sandbox-dns" addr ]) (addr: [ "--sanebox-dns" addr ])
dns dns
) )
); );
sandboxFlags = [ sandboxFlags = [
"--sane-sandbox-method" method "--sanebox-method" method
] ]
++ netItems ++ netItems
++ allowPaths allowedPaths ++ allowPaths allowedPaths
++ capabilityFlags ++ capabilityFlags
++ lib.optionals (autodetectCliPaths != null) [ "--sane-sandbox-autodetect" autodetectCliPaths ] ++ lib.optionals (autodetectCliPaths != null) [ "--sanebox-autodetect" autodetectCliPaths ]
++ lib.optionals whitelistPwd [ "--sane-sandbox-add-pwd" ] ++ lib.optionals whitelistPwd [ "--sanebox-add-pwd" ]
++ cacheLinks symlinkCache ++ cacheLinks symlinkCache
++ extraConfig; ++ extraConfig;
in in
writeTextFile { writeTextFile {
name = "${pkgName}-sandbox-profiles"; name = "${pkgName}-sandbox-profiles";
destination = "/share/sane-sandboxed/profiles/${pkgName}.profile"; destination = "/share/sanebox/profiles/${pkgName}.profile";
text = builtins.concatStringsSep "\n" sandboxFlags; text = builtins.concatStringsSep "\n" sandboxFlags;
} }

View File

@@ -2,16 +2,16 @@
, buildPackages , buildPackages
, runCommandLocal , runCommandLocal
, runtimeShell , runtimeShell
, sane-sandboxed , sanebox
, symlinkJoin , symlinkJoin
, writeShellScriptBin , writeShellScriptBin
, writeTextFile , writeTextFile
}: }:
let let
fakeSaneSandboxed = writeShellScriptBin "sane-sandboxed" '' fakeSaneSandboxed = writeShellScriptBin "sanebox" ''
# behave like the real sane-sandboxed with SANE_SANDBOX_DISABLE=1, # behave like the real sanebox with SANEBOX_DISABLE=1,
# but in a manner which avoids taking a dependency on the real sane-sandboxed. # but in a manner which avoids taking a dependency on the real sanebox.
# the primary use for this is to allow a package's `check` phase to work even when sane-sandboxed isn't available. # the primary use for this is to allow a package's `check` phase to work even when sanebox isn't available.
_origArgs=($@) _origArgs=($@)
# throw away all arguments until we find the path to the binary which is being sandboxed # throw away all arguments until we find the path to the binary which is being sandboxed
@@ -19,12 +19,12 @@ let
shift shift
done done
if [ "$#" -eq 0 ]; then if [ "$#" -eq 0 ]; then
>&2 echo "sane-sandbox: failed to parse args: ''${_origArgs[*]}" >&2 echo "sanebox (mock): failed to parse args: ''${_origArgs[*]}"
exit 1 exit 1
fi fi
if [ -z "$SANE_SANDBOX_DISABLE" ]; then if [ -z "$SANEBOX_DISABLE" ]; then
>&2 echo "sane-sandbox: not called with SANE_SANDBOX_DISABLE=1; unsure how to sandbox: ''${_origArgs[*]}" >&2 echo "sanebox (mock): not called with SANEBOX_DISABLE=1; unsure how to sandbox: ''${_origArgs[*]}"
exit 1 exit 1
fi fi
# assume that every argument after the binary name is an argument for the binary and not for the sandboxer. # assume that every argument after the binary name is an argument for the binary and not for the sandboxer.
@@ -39,14 +39,14 @@ let
# take an existing package, which may have a `bin/` folder as well as `share/` etc, # take an existing package, which may have a `bin/` folder as well as `share/` etc,
# and patch the `bin/` items in-place # and patch the `bin/` items in-place
sandboxBinariesInPlace = sane-sandboxed': extraSandboxArgsStr: pkgName: pkg: pkg.overrideAttrs (unwrapped: { sandboxBinariesInPlace = sanebox': extraSandboxArgsStr: pkgName: pkg: pkg.overrideAttrs (unwrapped: {
# disable the sandbox and inject a minimal fake sandboxer which understands that flag, # disable the sandbox and inject a minimal fake sandboxer which understands that flag,
# in order to support packages which invoke sandboxed apps in their check phase. # in order to support packages which invoke sandboxed apps in their check phase.
# note that it's not just for packages which invoke their *own* binaries in check phase, # note that it's not just for packages which invoke their *own* binaries in check phase,
# but also packages which invoke OTHER PACKAGES' sandboxed binaries. # but also packages which invoke OTHER PACKAGES' sandboxed binaries.
# hence, put the fake sandbox in nativeBuildInputs instead of nativeCheckInputs. # hence, put the fake sandbox in nativeBuildInputs instead of nativeCheckInputs.
env = (unwrapped.env or {}) // { env = (unwrapped.env or {}) // {
SANE_SANDBOX_DISABLE = 1; SANEBOX_DISABLE = 1;
}; };
# TODO: handle multi-output packages; until then, squash lib into the main output, particularly for `libexec`. # TODO: handle multi-output packages; until then, squash lib into the main output, particularly for `libexec`.
# (this line here only affects `inplace` style wrapping) # (this line here only affects `inplace` style wrapping)
@@ -55,7 +55,7 @@ let
fakeSaneSandboxed fakeSaneSandboxed
]; ];
disallowedReferences = (unwrapped.disallowedReferences or []) ++ [ disallowedReferences = (unwrapped.disallowedReferences or []) ++ [
# the fake sandbox gates itself behind SANE_SANDBOX_DISABLE, so if it did end up deployed # the fake sandbox gates itself behind SANEBOX_DISABLE, so if it did end up deployed
# then it wouldn't permit anything not already permitted. but it would still be annoying. # then it wouldn't permit anything not already permitted. but it would still be annoying.
fakeSaneSandboxed fakeSaneSandboxed
]; ];
@@ -79,7 +79,7 @@ let
mv "$_dir/$_name" "$_dir/.sandboxed/" mv "$_dir/$_name" "$_dir/.sandboxed/"
fi fi
echo '#!${runtimeShell}' > "$_dir/$_name" echo '#!${runtimeShell}' > "$_dir/$_name"
echo 'exec ${sane-sandboxed'} --sane-sandbox-profile ${pkgName}' "$_dir/.sandboxed/$_name" '"$@"' >> "$_dir/$_name" echo 'exec ${sanebox'} --sanebox-profile ${pkgName}' "$_dir/.sandboxed/$_name" '"$@"' >> "$_dir/$_name"
chmod +x "$_dir/$_name" chmod +x "$_dir/$_name"
} }
@@ -227,9 +227,9 @@ let
_numExec=0 _numExec=0
_checkExecutable() { _checkExecutable() {
echo "checking if $1 is sandboxed" echo "checking if $1 is sandboxed"
PATH="${finalAttrs.finalPackage}/bin:${sane-sandboxed}/bin:$PATH" \ PATH="${finalAttrs.finalPackage}/bin:${sanebox}/bin:$PATH" \
SANE_SANDBOX_DISABLE=1 \ SANEBOX_DISABLE=1 \
"$1" --sane-sandbox-replace-cli echo "printing for test" \ "$1" --sanebox-replace-cli echo "printing for test" \
| grep "printing for test" | grep "printing for test"
_numExec=$(( $_numExec + 1 )) _numExec=$(( $_numExec + 1 ))
} }
@@ -270,12 +270,12 @@ let
make-sandboxed = { pkgName, package, wrapperType, embedSandboxer ? false, extraSandboxerArgs ? [], passthru ? {} }@args: make-sandboxed = { pkgName, package, wrapperType, embedSandboxer ? false, extraSandboxerArgs ? [], passthru ? {} }@args:
let let
unsandboxed = package; unsandboxed = package;
sane-sandboxed' = if embedSandboxer then sanebox' = if embedSandboxer then
# optionally hard-code the sandboxer. this forces rebuilds, but allows deep iteration w/o deploys. # optionally hard-code the sandboxer. this forces rebuilds, but allows deep iteration w/o deploys.
lib.getExe sane-sandboxed lib.getExe sanebox
else else
#v prefer to load by bin name to reduce rebuilds #v prefer to load by bin name to reduce rebuilds
sane-sandboxed.meta.mainProgram sanebox.meta.mainProgram
; ;
extraSandboxerArgsStr = lib.escapeShellArgs extraSandboxerArgs; extraSandboxerArgsStr = lib.escapeShellArgs extraSandboxerArgs;
@@ -288,14 +288,14 @@ let
# regardless of which one is chosen here, all other options are exposed via `passthru`. # regardless of which one is chosen here, all other options are exposed via `passthru`.
sandboxedBy = { sandboxedBy = {
inplace = sandboxBinariesInPlace inplace = sandboxBinariesInPlace
sane-sandboxed' sanebox'
extraSandboxerArgsStr extraSandboxerArgsStr
pkgName pkgName
(makeHookable unsandboxed); (makeHookable unsandboxed);
wrappedDerivation = let wrappedDerivation = let
sandboxedBin = sandboxBinariesInPlace sandboxedBin = sandboxBinariesInPlace
sane-sandboxed' sanebox'
extraSandboxerArgsStr extraSandboxerArgsStr
pkgName pkgName
(symlinkBinaries pkgName unsandboxed); (symlinkBinaries pkgName unsandboxed);

View File

@@ -97,7 +97,7 @@ vpnDo() {
debug "vpnDo with:" debug "vpnDo with:"
debug " bridgeDevice='$bridgeDevice'" debug " bridgeDevice='$bridgeDevice'"
debug " dns='$dns'" debug " dns='$dns'"
# TODO: switch to bwrap, or `sane-sandboxed`! # TODO: switch to bwrap, or `sanebox`!
firejail --noprofile --net="$bridgeDevice" --dns="$dns" "$@" firejail --noprofile --net="$bridgeDevice" --dns="$dns" "$@"
} }

View File

@@ -5,26 +5,26 @@
, landlock-sandboxer , landlock-sandboxer
, libcap , libcap
, substituteAll , substituteAll
, profileDir ? "/share/sane-sandboxed/profiles" , profileDir ? "/share/sanebox/profiles"
}: }:
let let
sane-sandboxed = substituteAll { sanebox = substituteAll {
src = ./sane-sandboxed; src = ./sanebox;
inherit bash bubblewrap firejail libcap; inherit bash bubblewrap firejail libcap;
landlockSandboxer = landlock-sandboxer; landlockSandboxer = landlock-sandboxer;
firejailProfileDirs = "/run/current-system/sw/etc/firejail /etc/firejail ${firejail}/etc/firejail"; firejailProfileDirs = "/run/current-system/sw/etc/firejail /etc/firejail ${firejail}/etc/firejail";
}; };
self = stdenv.mkDerivation { self = stdenv.mkDerivation {
pname = "sane-sandboxed"; pname = "sanebox";
version = "0.1"; version = "0.1";
src = sane-sandboxed; src = sanebox;
dontUnpack = true; dontUnpack = true;
buildPhase = '' buildPhase = ''
runHook preBuild runHook preBuild
substituteAll "$src" sane-sandboxed \ substituteAll "$src" sanebox \
--replace-fail '@out@' "$out" --replace-fail '@out@' "$out"
runHook postBuild runHook postBuild
''; '';
@@ -33,7 +33,7 @@ let
runHook preInstall runHook preInstall
install -d "$out" install -d "$out"
install -d "$out/bin" install -d "$out/bin"
install -m 755 sane-sandboxed $out/bin/sane-sandboxed install -m 755 sanebox $out/bin/sanebox
runHook postInstall runHook postInstall
''; '';
@@ -42,7 +42,7 @@ let
withProfiles = profiles: self.overrideAttrs (base: { withProfiles = profiles: self.overrideAttrs (base: {
inherit profiles; inherit profiles;
postInstall = (base.postInstall or "") + '' postInstall = (base.postInstall or "") + ''
install -d $out/share/sane-sandboxed install -d $out/share/sanebox
ln -s "${profiles}/${profileDir}" "$out/${profileDir}" ln -s "${profiles}/${profileDir}" "$out/${profileDir}"
''; '';
}); });
@@ -55,7 +55,7 @@ let
1. to abstract over the particular sandbox implementation (bwrap, firejail, ...). 1. to abstract over the particular sandbox implementation (bwrap, firejail, ...).
2. to modify sandbox settings without forcing a rebuild of the sandboxed package. 2. to modify sandbox settings without forcing a rebuild of the sandboxed package.
''; '';
mainProgram = "sane-sandboxed"; mainProgram = "sanebox";
}; };
}; };
in self in self

View File

@@ -14,7 +14,7 @@ debug() {
} }
# if requested, enable debugging as early as possible # if requested, enable debugging as early as possible
if [ -n "$SANE_SANDBOX_DEBUG" ]; then if [ -n "$SANEBOX_DEBUG" ]; then
enableDebug enableDebug
fi fi
@@ -84,57 +84,57 @@ firejailFlags=()
bwrapFlags=() bwrapFlags=()
usage() { usage() {
echo 'sane-sandboxed: run a program inside a sandbox' echo 'sanebox: run a program inside a sandbox'
echo 'USAGE: sane-sandboxed [sandbox-arg ...] program [sandbox-arg|program-arg ...] [--] [program-arg ...]' echo 'USAGE: sanebox [sandbox-arg ...] program [sandbox-arg|program-arg ...] [--] [program-arg ...]'
echo '' echo ''
echo 'sandbox args and program args may be intermixed, but the first `--` anywhere signals the end of the sandbox args and the start of program args' echo 'sandbox args and program args may be intermixed, but the first `--` anywhere signals the end of the sandbox args and the start of program args'
echo echo
echo 'sandbox args:' echo 'sandbox args:'
echo ' --sane-sandbox-help' echo ' --sanebox-help'
echo ' show this message' echo ' show this message'
echo ' --sane-sandbox-debug' echo ' --sanebox-debug'
echo ' print debug messages to stderr' echo ' print debug messages to stderr'
echo ' --sane-sandbox-replace-cli <bin>' echo ' --sanebox-replace-cli <bin>'
echo ' invoke <bin> under the sandbox instead of any program previously listed' echo ' invoke <bin> under the sandbox instead of any program previously listed'
echo ' also clears and earlier arguments intended for the program' echo ' also clears and earlier arguments intended for the program'
echo ' --sane-sandbox-disable' echo ' --sanebox-disable'
echo ' invoke the program directly, instead of inside a sandbox' echo ' invoke the program directly, instead of inside a sandbox'
echo ' --sane-sandbox-dry-run' echo ' --sanebox-dry-run'
echo ' show what would be `exec`uted but do not perform any action' echo ' show what would be `exec`uted but do not perform any action'
echo ' --sane-sandbox-method <bwrap|capshonly|firejail|landlock|none>' echo ' --sanebox-method <bwrap|capshonly|firejail|landlock|none>'
echo ' use a specific sandboxer' echo ' use a specific sandboxer'
echo ' --sane-sandbox-autodetect <existing|existingFile|existingFileOrParent|existingOrParent|parent>' echo ' --sanebox-autodetect <existing|existingFile|existingFileOrParent|existingOrParent|parent>'
echo ' add files which appear later as CLI arguments into the sandbox' echo ' add files which appear later as CLI arguments into the sandbox'
echo ' --sane-sandbox-cap <sys_admin|net_raw|net_admin|...>' echo ' --sanebox-cap <sys_admin|net_raw|net_admin|...>'
echo ' allow the sandboxed program to use the provided linux capability (both inside and outside the sandbox)' echo ' allow the sandboxed program to use the provided linux capability (both inside and outside the sandbox)'
echo ' --sane-sandbox-portal' echo ' --sanebox-portal'
echo ' set environment variables so that the sandboxed program will attempt to use xdg-desktop-portal for operations like opening files' echo ' set environment variables so that the sandboxed program will attempt to use xdg-desktop-portal for operations like opening files'
echo ' --sane-sandbox-no-portal' echo ' --sanebox-no-portal'
echo ' undo a previous `--sane-sandbox-portal` arg' echo ' undo a previous `--sanebox-portal` arg'
echo ' --sane-sandbox-dns <server>' echo ' --sanebox-dns <server>'
echo ' --sane-sandbox-firejail-arg <arg>' echo ' --sanebox-firejail-arg <arg>'
echo ' --sane-sandbox-bwrap-arg <arg>' echo ' --sanebox-bwrap-arg <arg>'
echo ' --sane-sandbox-net <iface>' echo ' --sanebox-net <iface>'
echo ' --sane-sandbox-keep-namespace <cgroup|ipc|pid|uts|all>' echo ' --sanebox-keep-namespace <cgroup|ipc|pid|uts|all>'
echo ' do not unshare the provided linux namespace' echo ' do not unshare the provided linux namespace'
echo ' --sane-sandbox-path <path>' echo ' --sanebox-path <path>'
echo ' allow access to the host <path> within the sandbox' echo ' allow access to the host <path> within the sandbox'
echo ' --sane-sandbox-add-pwd' echo ' --sanebox-add-pwd'
echo ' shorthand for `--sane-sandbox-path $PWD`' echo ' shorthand for `--sanebox-path $PWD`'
echo ' --sane-sandbox-profile <profile>' echo ' --sanebox-profile <profile>'
echo ' --sane-sandbox-profile-dir <dir>' echo ' --sanebox-profile-dir <dir>'
echo ' --sane-sandbox-cache-symlink <from> <to>' echo ' --sanebox-cache-symlink <from> <to>'
echo ' assume that <from> is a symlink to <to>' echo ' assume that <from> is a symlink to <to>'
echo ' performance optimization to avoid spawning a readlink subshell' echo ' performance optimization to avoid spawning a readlink subshell'
echo echo
echo 'the following environment variables are also considered and propagated to children:' echo 'the following environment variables are also considered and propagated to children:'
echo ' SANE_SANDBOX_DISABLE=1' echo ' SANEBOX_DISABLE=1'
echo ' equivalent to `--sane-sandbox-disable`' echo ' equivalent to `--sanebox-disable`'
echo ' SANE_SANDBOX_DEBUG=1' echo ' SANEBOX_DEBUG=1'
echo ' equivalent to `--sane-sandbox-debug`, but activates earlier' echo ' equivalent to `--sanebox-debug`, but activates earlier'
echo ' SANE_SANDBOX_PREPEND=...' echo ' SANEBOX_PREPEND=...'
echo ' act as though the provided arg string appeared at the start of the CLI' echo ' act as though the provided arg string appeared at the start of the CLI'
echo ' SANE_SANDBOX_APPEND=...' echo ' SANEBOX_APPEND=...'
echo ' act as though the provided arg string appeared at the end of the CLI' echo ' act as though the provided arg string appeared at the end of the CLI'
} }
@@ -342,7 +342,7 @@ derefOnce() {
## HELPERS ## HELPERS
loadProfileByPath() { loadProfileByPath() {
# profile format is simply a list of arguments one would pass to this sane-sandboxed script itself, # profile format is simply a list of arguments one would pass to this sanebox script itself,
# with one argument per line # with one argument per line
readarray -t _profArgs < "$1" readarray -t _profArgs < "$1"
parseArgs "${_profArgs[@]}" parseArgs "${_profArgs[@]}"
@@ -353,7 +353,7 @@ tryLoadProfileByName() {
if [ "${profile:0:1}" = "/" ]; then if [ "${profile:0:1}" = "/" ]; then
# absolute path to profile. # absolute path to profile.
# consider it an error if it doesn't exist. # consider it an error if it doesn't exist.
# in general, prefer to use `--sane-sandbox-profile-dir` and specify the profile by name. # in general, prefer to use `--sanebox-profile-dir` and specify the profile by name.
# doing so maximizes compatibility with anything else that uses the name, like firejail. # doing so maximizes compatibility with anything else that uses the name, like firejail.
loadProfileByPath "$profile" loadProfileByPath "$profile"
else else
@@ -372,7 +372,7 @@ tryLoadProfileByName() {
initDefaultProfileDirs() { initDefaultProfileDirs() {
for d in ${XDG_DATA_DIRS//:/ }; do for d in ${XDG_DATA_DIRS//:/ }; do
profileDirs+=("$d/sane-sandboxed/profiles") profileDirs+=("$d/sanebox/profiles")
done done
} }
@@ -452,8 +452,8 @@ parseArgs() {
(--) (--)
# rest of args are for the CLI, and not for us. # rest of args are for the CLI, and not for us.
# consider two cases: # consider two cases:
# - sane-sandboxed --sane-sandbox-flag1 -- /nix/store/.../mpv --arg0 arg1 # - sanebox --sanebox-flag1 -- /nix/store/.../mpv --arg0 arg1
# - sane-sandboxed /nix/store/.../mpv --arg0 -- arg1 # - sanebox /nix/store/.../mpv --arg0 -- arg1
# in the first case, we swallow the -- and treat the rest as CLI args. # in the first case, we swallow the -- and treat the rest as CLI args.
# in the second case, the -- is *probably* intended for the application. # in the second case, the -- is *probably* intended for the application.
# but it could be meant for us. do the most conservative thing here # but it could be meant for us. do the most conservative thing here
@@ -466,30 +466,30 @@ parseArgs() {
parseArgsExtra+=("$@") parseArgsExtra+=("$@")
break break
;; ;;
(--sane-sandbox-help) (--sanebox-help)
usage usage
exit 0 exit 0
;; ;;
(--sane-sandbox-debug) (--sanebox-debug)
enableDebug enableDebug
;; ;;
(--sane-sandbox-replace-cli) (--sanebox-replace-cli)
# keep the sandbox flags, but clear any earlier CLI args. # keep the sandbox flags, but clear any earlier CLI args.
# this lets the user do things like `mpv --sane-sandbox-replace-cli sh` to enter a shell # this lets the user do things like `mpv --sanebox-replace-cli sh` to enter a shell
# with the sandbox that `mpv` would see. # with the sandbox that `mpv` would see.
parseArgsExtra=() parseArgsExtra=()
;; ;;
(--sane-sandbox-disable) (--sanebox-disable)
isDisable=1 isDisable=1
;; ;;
(--sane-sandbox-dry-run) (--sanebox-dry-run)
isDryRun=1 isDryRun=1
;; ;;
(--sane-sandbox-method) (--sanebox-method)
method="$1" method="$1"
shift shift
;; ;;
(--sane-sandbox-autodetect) (--sanebox-autodetect)
# autodetect: crawl the CLI program's args & bind any which look like paths into the sandbox. # autodetect: crawl the CLI program's args & bind any which look like paths into the sandbox.
# this is handy for e.g. media players or document viewers. # this is handy for e.g. media players or document viewers.
# it's best combined with some two-tiered thing. # it's best combined with some two-tiered thing.
@@ -497,43 +497,43 @@ parseArgs() {
autodetect="$1" autodetect="$1"
shift shift
;; ;;
(--sane-sandbox-cap) (--sanebox-cap)
local cap="$1" local cap="$1"
shift shift
capabilities+=("$cap") capabilities+=("$cap")
;; ;;
(--sane-sandbox-portal) (--sanebox-portal)
# instruct glib/gtk apps to perform actions such as opening external files via dbus calls to org.freedesktop.portal.*. # instruct glib/gtk apps to perform actions such as opening external files via dbus calls to org.freedesktop.portal.*.
# note that GIO_USE_PORTALS primarily acts as a *fallback*: apps only open files via the portal if they don't know how to themelves. # note that GIO_USE_PORTALS primarily acts as a *fallback*: apps only open files via the portal if they don't know how to themelves.
# this switch is typically accompanied by removing all MIME associations from the app's view, then. # this switch is typically accompanied by removing all MIME associations from the app's view, then.
# GTK_USE_PORTALS is the old name, beginning to be phased out as of 2023-10-02 # GTK_USE_PORTALS is the old name, beginning to be phased out as of 2023-10-02
portalEnv=("GIO_USE_PORTALS=1" "GTK_USE_PORTAL=1" "NIXOS_XDG_OPEN_USE_PORTAL=1") portalEnv=("GIO_USE_PORTALS=1" "GTK_USE_PORTAL=1" "NIXOS_XDG_OPEN_USE_PORTAL=1")
;; ;;
(--sane-sandbox-no-portal) (--sanebox-no-portal)
# override a previous --sane-sandbox-portal call # override a previous --sanebox-portal call
portalEnv=() portalEnv=()
;; ;;
(--sane-sandbox-dns) (--sanebox-dns)
# N.B.: these named temporary variables ensure that "set -x" causes $1 to be printed # N.B.: these named temporary variables ensure that "set -x" causes $1 to be printed
local dns="$1" local dns="$1"
shift shift
dns+=("$dns") dns+=("$dns")
;; ;;
(--sane-sandbox-firejail-arg) (--sanebox-firejail-arg)
local fjFlag="$1" local fjFlag="$1"
shift shift
firejailFlags+=("$fjFlag") firejailFlags+=("$fjFlag")
;; ;;
(--sane-sandbox-bwrap-arg) (--sanebox-bwrap-arg)
local bwrapFlag="$1" local bwrapFlag="$1"
shift shift
bwrapFlags+=("$bwrapFlag") bwrapFlags+=("$bwrapFlag")
;; ;;
(--sane-sandbox-net) (--sanebox-net)
net="$1" net="$1"
shift shift
;; ;;
(--sane-sandbox-keep-namespace) (--sanebox-keep-namespace)
local namespace="$1" local namespace="$1"
shift shift
if [ "$namespace" = all ]; then if [ "$namespace" = all ]; then
@@ -542,29 +542,29 @@ parseArgs() {
keepNamespace+=("$namespace") keepNamespace+=("$namespace")
fi fi
;; ;;
(--sane-sandbox-path) (--sanebox-path)
local path="$1" local path="$1"
shift shift
relativeToPwd _absPath "$path" relativeToPwd _absPath "$path"
paths+=("$_absPath") paths+=("$_absPath")
;; ;;
(--sane-sandbox-add-pwd) (--sanebox-add-pwd)
paths+=("$PWD") paths+=("$PWD")
;; ;;
(--sane-sandbox-profile) (--sanebox-profile)
# load the profile *immediately*, inline. # load the profile *immediately*, inline.
# this way, user arguments which come later on the CLI can override any profile config, v.s. if profile loading were defered. # this way, user arguments which come later on the CLI can override any profile config, v.s. if profile loading were defered.
tryLoadProfileByName "$1" tryLoadProfileByName "$1"
shift shift
;; ;;
(--sane-sandbox-profile-dir) (--sanebox-profile-dir)
# add another directory in which to search for profiles, # add another directory in which to search for profiles,
# and give it *greater* precedence than the existing search directories (i.e. override the default profile) # and give it *greater* precedence than the existing search directories (i.e. override the default profile)
local dir="$1" local dir="$1"
shift shift
profileDirs=("$dir" "${profileDirs[@]}") profileDirs=("$dir" "${profileDirs[@]}")
;; ;;
(--sane-sandbox-cache-symlink) (--sanebox-cache-symlink)
local from="$1" local from="$1"
shift shift
local to="$1" local to="$1"
@@ -952,14 +952,14 @@ removeSubpaths() {
### parse arguments, with consideration of any which may be injected via the environment ### parse arguments, with consideration of any which may be injected via the environment
parseArgsAndEnvironment() { parseArgsAndEnvironment() {
if [ -n "$SANE_SANDBOX_DISABLE" ]; then if [ -n "$SANEBOX_DISABLE" ]; then
isDisable=1 isDisable=1
fi fi
test -n "$SANE_SANDBOX_PREPEND" && parseArgs $SANE_SANDBOX_PREPEND test -n "$SANEBOX_PREPEND" && parseArgs $SANEBOX_PREPEND
parseArgs "$@" parseArgs "$@"
cliArgs+=("${parseArgsExtra[@]}") cliArgs+=("${parseArgsExtra[@]}")
test -n "$SANE_SANDBOX_APPEND" && parseArgs $SANE_SANDBOX_APPEND test -n "$SANEBOX_APPEND" && parseArgs $SANEBOX_APPEND
} }
### convert generic args into sandbox-specific args ### convert generic args into sandbox-specific args
@@ -998,13 +998,13 @@ initDefaultProfileDirs
parseArgsAndEnvironment "$@" parseArgsAndEnvironment "$@"
# variables meant to be inherited # variables meant to be inherited
# N.B.: SANE_SANDBOX_DEBUG FREQUENTLY BREAKS APPLICATIONS WHICH PARSE STDOUT # N.B.: SANEBOX_DEBUG FREQUENTLY BREAKS APPLICATIONS WHICH PARSE STDOUT
# example is wireshark parsing stdout of dumpcap; # example is wireshark parsing stdout of dumpcap;
# in such a case invoke the app with --sane-sandbox-debug instead of the env var. # in such a case invoke the app with --sanebox-debug instead of the env var.
export SANE_SANDBOX_DEBUG="$SANE_SANDBOX_DEBUG" export SANEBOX_DEBUG="$SANEBOX_DEBUG"
export SANE_SANDBOX_DISABLE="$SANE_SANDBOX_DISABLE" export SANEBOX_DISABLE="$SANEBOX_DISABLE"
export SANE_SANDBOX_PREPEND="$SANE_SANDBOX_PREPEND" export SANEBOX_PREPEND="$SANEBOX_PREPEND"
export SANE_SANDBOX_APPEND="$SANE_SANDBOX_APPEND" export SANEBOX_APPEND="$SANEBOX_APPEND"
if [ -z "$isDisable" ]; then if [ -z "$isDisable" ]; then
# method-specific setup could add additional paths that need binding, so do that before canonicalization # method-specific setup could add additional paths that need binding, so do that before canonicalization

View File

@@ -61,10 +61,10 @@ let
sane-cast = callPackage ./additional/sane-cast { }; sane-cast = callPackage ./additional/sane-cast { };
sane-die-with-parent = callPackage ./additional/sane-die-with-parent { }; sane-die-with-parent = callPackage ./additional/sane-die-with-parent { };
sane-open = callPackage ./additional/sane-open { }; sane-open = callPackage ./additional/sane-open { };
sane-sandboxed = callPackage ./additional/sane-sandboxed { };
sane-screenshot = callPackage ./additional/sane-screenshot { }; sane-screenshot = callPackage ./additional/sane-screenshot { };
sane-scripts = lib.recurseIntoAttrs (callPackage ./additional/sane-scripts { }); sane-scripts = lib.recurseIntoAttrs (callPackage ./additional/sane-scripts { });
sane-weather = callPackage ./additional/sane-weather { }; sane-weather = callPackage ./additional/sane-weather { };
sanebox = callPackage ./additional/sanebox { };
schlock = callPackage ./additional/schlock { }; schlock = callPackage ./additional/schlock { };
signal-desktop-from-src = callPackage ./additional/signal-desktop-from-src { }; signal-desktop-from-src = callPackage ./additional/signal-desktop-from-src { };
static-nix-shell = callPackage ./additional/static-nix-shell { }; static-nix-shell = callPackage ./additional/static-nix-shell { };