modules/programs: sandboxing: dereference symlinks and also include those in the sandbox

This commit is contained in:
Colin 2024-02-12 12:48:02 +00:00
parent eee3e138ff
commit a90b5b53db

View File

@ -2,6 +2,7 @@
let
saneCfg = config.sane;
cfg = config.sane.programs;
path-lib = sane-lib.path;
# create a map:
# {
@ -40,21 +41,51 @@ let
let
makeProfile = pkgs.callPackage ./make-sandbox-profile.nix { };
makeSandboxed = pkgs.callPackage ./make-sandboxed.nix { sane-sandboxed = config.sane.sandboxHelper; };
# removeStorePaths: [ str ] -> [ str ], but remove store paths, because nix evals aren't allowed to contain any (for purity reasons?)
removeStorePaths = lib.filter (p: !(lib.hasPrefix "/nix/store" p));
# onlySymlinks: [ str ] -> [ str ], keeping only those strings which represent paths that are symlinks
onlySymlinks = lib.filter
(p: (config.sane.fs."${p}" or { symlink = null; }).symlink != null);
# expandSymlinksOnce: [ str ] -> [ str ], returning all the original paths plus dereferencing any symlinks and adding their targets to this list.
derefSymlinks = paths: builtins.map
(p: config.sane.fs."${p}".symlink.target)
(onlySymlinks paths)
;
expandSymlinksOnce = paths: lib.unique (paths ++ removeStorePaths (derefSymlinks paths));
expandSymlinks = lib.converge expandSymlinksOnce;
vpn = lib.findSingle (v: v.default) null null (builtins.attrValues config.sane.vpn);
sandboxProfilesFor = userName: let
homeDir = config.sane.users."${userName}".home;
uid = config.users.users."${userName}".uid;
xdgRuntimeDir = "/run/user/${builtins.toString uid}";
fullHomePaths = lib.optionals (userName != null) (
builtins.map
(p: "${homeDir}/${p}")
(p: path-lib.concat [ homeDir p ])
(builtins.attrNames fs ++ builtins.attrNames persist.byPath ++ sandbox.extraHomePaths)
);
fullRuntimePaths = lib.optionals (userName != null) (
builtins.map
(p: "${xdgRuntimeDir}/${p}")
(p: path-lib.concat [ xdgRuntimeDir p ])
sandbox.extraRuntimePaths
);
allowedRootPaths = [
"/nix/store"
"/bin/sh"
"/etc" #< especially for /etc/profiles/per-user/$USER/bin
"/run/current-system" #< for basics like `ls`, and all this program's `suggestedPrograms` (/run/current-system/sw/bin)
"/run/wrappers" #< SUID wrappers, in this case so that firejail can be re-entrant
# "/bin/sh" #< to allow `firejail --join=...` (doesn't work)
"/run/systemd/resolve" #< to allow reading /etc/resolv.conf, which ultimately symlinks here
# /run/opengl-driver is a symlink into /nix/store; needed by e.g. mpv
"/run/opengl-driver"
"/run/opengl-driver-32" #< XXX: doesn't exist on aarch64?
"/run/secrets/home" #< TODO: this could be restricted per-app based on the HOME paths they need
"/usr/bin/env"
] ++ sandbox.extraPaths ++ fullHomePaths ++ fullRuntimePaths;
in makeProfile {
inherit pkgName;
inherit (sandbox)
@ -72,21 +103,7 @@ let
vpn.dns
else
null;
allowedRootPaths = [
"/nix/store"
"/bin/sh"
"/etc" #< especially for /etc/profiles/per-user/$USER/bin
"/run/current-system" #< for basics like `ls`, and all this program's `suggestedPrograms` (/run/current-system/sw/bin)
"/run/wrappers" #< SUID wrappers, in this case so that firejail can be re-entrant
# "/bin/sh" #< to allow `firejail --join=...` (doesn't work)
"/run/systemd/resolve" #< to allow reading /etc/resolv.conf, which ultimately symlinks here
# /run/opengl-driver is a symlink into /nix/store; needed by e.g. mpv
"/run/opengl-driver"
"/run/opengl-driver-32" #< XXX: doesn't exist on aarch64?
"/run/secrets/home" #< TODO: this could be restricted per-app based on the HOME paths they need
"/usr/bin/env"
] ++ sandbox.extraPaths ++ fullHomePaths ++ fullRuntimePaths;
allowedRootPaths = expandSymlinks allowedRootPaths;
};
in
makeSandboxed {