programs: dereference not just the leaf, but any part of the path, when determining a program's sandbox closure

This commit is contained in:
Colin 2024-02-23 05:24:13 +00:00
parent a402822084
commit 170eeeacc4
3 changed files with 37 additions and 12 deletions

View File

@ -3,7 +3,7 @@
let
sane-lib = rec {
feeds = import ./feeds.nix { inherit lib; };
fs = import ./fs.nix { inherit lib; };
fs = import ./fs.nix { inherit lib sane-lib; };
merge = import ./merge.nix { inherit lib sane-lib; };
path = import ./path.nix { inherit lib; };
types = import ./types.nix { inherit lib; };

View File

@ -1,10 +1,37 @@
{ lib, ... }:
{ lib, sane-lib, ... }:
rec {
let
sane-path = sane-lib.path;
in rec {
wanted = lib.attrsets.unionOfDisjoint { wantedBeforeBy = [ "multi-user.target" ]; };
wantedDir = wanted { dir = {}; };
wantedSymlink = symlink: wanted { inherit symlink; };
wantedSymlinkTo = target: wantedSymlink { inherit target; };
wantedText = text: wantedSymlink { inherit text; };
# Type: derefSymlinkOrNul :: config.sane.fs.type -> str -> (str|null)
derefSymlinkOrNull = fs: logical: let
symlinkedPrefixes = lib.filter
(p: ((fs."${p}" or {}).symlink or null) != null)
(sane-path.walk "/" logical);
firstSymlink = builtins.head symlinkedPrefixes;
firstSymlinkDest = "${firstSymlink}".symlink.target;
firstSymlinkParent = sane-path.parent firstSymlink;
firstSymlinkDestAbs = if lib.hasPrefix "/" firstSymlinkDest then
firstSymlinkDest
else
sane-path.join [ firstSymlinkParent firstSymlinkDest ];
in
if symlinkedPrefixes != [] then
firstSymlinkDestAbs
else
null
;
derefSymlink = fs: logical:
if derefSymlinkOrNull fs logical != null then
derefSymlinkOrNull fs logical
else
logical
;
}

View File

@ -2,6 +2,7 @@
let
saneCfg = config.sane;
cfg = config.sane.programs;
fs-lib = sane-lib.fs;
path-lib = sane-lib.path;
# create a map:
@ -43,17 +44,14 @@ let
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);
removeStorePaths = paths: lib.filter (p: !(lib.hasPrefix "/nix/store" p)) paths;
# derefSymlinks: [ str ] -> [ str ]: for each path which is a symlink (or a child of a symlink'd dir), dereference one layer of symlink. else, drop it from the list.
derefSymlinks' = paths: builtins.map (fs-lib.derefSymlinkOrNull fs) paths;
derefSymlinks = paths: lib.filter (p: p != null) (derefSymlinks' paths);
# 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;
expandSymlinks = paths: lib.converge expandSymlinksOnce paths;
vpn = lib.findSingle (v: v.default) null null (builtins.attrValues config.sane.vpn);