modules/programs: sandboxing: dereference symlinks and also include those in the sandbox
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
let
|
let
|
||||||
saneCfg = config.sane;
|
saneCfg = config.sane;
|
||||||
cfg = config.sane.programs;
|
cfg = config.sane.programs;
|
||||||
|
path-lib = sane-lib.path;
|
||||||
|
|
||||||
# create a map:
|
# create a map:
|
||||||
# {
|
# {
|
||||||
@@ -40,21 +41,51 @@ let
|
|||||||
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.sandboxHelper; };
|
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);
|
vpn = lib.findSingle (v: v.default) null null (builtins.attrValues config.sane.vpn);
|
||||||
|
|
||||||
sandboxProfilesFor = userName: let
|
sandboxProfilesFor = userName: let
|
||||||
homeDir = config.sane.users."${userName}".home;
|
homeDir = config.sane.users."${userName}".home;
|
||||||
uid = config.users.users."${userName}".uid;
|
uid = config.users.users."${userName}".uid;
|
||||||
xdgRuntimeDir = "/run/user/${builtins.toString uid}";
|
xdgRuntimeDir = "/run/user/${builtins.toString uid}";
|
||||||
fullHomePaths = lib.optionals (userName != null) (
|
fullHomePaths = lib.optionals (userName != null) (
|
||||||
builtins.map
|
builtins.map
|
||||||
(p: "${homeDir}/${p}")
|
(p: path-lib.concat [ homeDir p ])
|
||||||
(builtins.attrNames fs ++ builtins.attrNames persist.byPath ++ sandbox.extraHomePaths)
|
(builtins.attrNames fs ++ builtins.attrNames persist.byPath ++ sandbox.extraHomePaths)
|
||||||
);
|
);
|
||||||
fullRuntimePaths = lib.optionals (userName != null) (
|
fullRuntimePaths = lib.optionals (userName != null) (
|
||||||
builtins.map
|
builtins.map
|
||||||
(p: "${xdgRuntimeDir}/${p}")
|
(p: path-lib.concat [ xdgRuntimeDir p ])
|
||||||
sandbox.extraRuntimePaths
|
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 {
|
in makeProfile {
|
||||||
inherit pkgName;
|
inherit pkgName;
|
||||||
inherit (sandbox)
|
inherit (sandbox)
|
||||||
@@ -72,21 +103,7 @@ let
|
|||||||
vpn.dns
|
vpn.dns
|
||||||
else
|
else
|
||||||
null;
|
null;
|
||||||
allowedRootPaths = [
|
allowedRootPaths = expandSymlinks 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
|
in
|
||||||
makeSandboxed {
|
makeSandboxed {
|
||||||
|
Reference in New Issue
Block a user