programs: sandboxing: make the profiles be generic across users
this is a step toward making the profile not even be dynamically loaded, since its content is no longer dynamic :)
This commit is contained in:
@@ -63,39 +63,74 @@ let
|
|||||||
|
|
||||||
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
|
allowedHomePaths = builtins.attrNames fs ++ builtins.attrNames persist.byPath ++ sandbox.extraHomePaths;
|
||||||
allowedHomePaths = builtins.attrNames fs ++ builtins.attrNames persist.byPath ++ sandbox.extraHomePaths;
|
allowedRunPaths = sandbox.extraRuntimePaths;
|
||||||
allowedRunPaths = sandbox.extraRuntimePaths;
|
allowedPaths = [
|
||||||
homeDir = config.sane.users."${userName}".home;
|
"/nix/store"
|
||||||
uid = config.users.users."${userName}".uid;
|
"/bin/sh"
|
||||||
xdgRuntimeDir = "/run/user/${builtins.toString uid}";
|
|
||||||
fullHomePaths = lib.optionals (userName != null) (
|
|
||||||
builtins.map
|
|
||||||
(p: path-lib.concat [ homeDir p ])
|
|
||||||
allowedHomePaths
|
|
||||||
);
|
|
||||||
fullRunPaths = lib.optionals (userName != null) (
|
|
||||||
builtins.map
|
|
||||||
(p: path-lib.concat [ xdgRuntimeDir p ])
|
|
||||||
allowedRunPaths
|
|
||||||
);
|
|
||||||
allowedPaths = [
|
|
||||||
"/nix/store"
|
|
||||||
"/bin/sh"
|
|
||||||
|
|
||||||
"/etc" #< especially for /etc/profiles/per-user/$USER/bin
|
"/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/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. TODO: remove!
|
"/run/wrappers" #< SUID wrappers, in this case so that firejail can be re-entrant. TODO: remove!
|
||||||
# /run/opengl-driver is a symlink into /nix/store; needed by e.g. mpv
|
# /run/opengl-driver is a symlink into /nix/store; needed by e.g. mpv
|
||||||
"/run/opengl-driver"
|
"/run/opengl-driver"
|
||||||
"/run/opengl-driver-32" #< XXX: doesn't exist on aarch64?
|
"/run/opengl-driver-32" #< XXX: doesn't exist on aarch64?
|
||||||
"/usr/bin/env"
|
"/usr/bin/env"
|
||||||
] ++ lib.optionals (config.services.resolved.enable) [
|
] ++ lib.optionals (config.services.resolved.enable) [
|
||||||
"/run/systemd/resolve" #< to allow reading /etc/resolv.conf, which ultimately symlinks here (if using systemd-resolved)
|
"/run/systemd/resolve" #< to allow reading /etc/resolv.conf, which ultimately symlinks here (if using systemd-resolved)
|
||||||
] ++ lib.optionals (builtins.elem "system" sandbox.whitelistDbus) [ "/run/dbus/system_bus_socket" ]
|
] ++ lib.optionals (builtins.elem "system" sandbox.whitelistDbus) [ "/run/dbus/system_bus_socket" ]
|
||||||
++ sandbox.extraPaths
|
++ sandbox.extraPaths
|
||||||
|
;
|
||||||
|
|
||||||
|
additionalPathsForUser = user: let
|
||||||
|
fullHomePaths = builtins.map
|
||||||
|
(p: path-lib.concat [ user.home p ])
|
||||||
|
allowedHomePaths
|
||||||
;
|
;
|
||||||
in makeProfile {
|
fullRunPaths = builtins.map
|
||||||
|
(p: path-lib.concat [ "/run/user/${builtins.toString user.uid}" p ])
|
||||||
|
allowedRunPaths
|
||||||
|
;
|
||||||
|
in
|
||||||
|
fullHomePaths ++ fullRunPaths;
|
||||||
|
# expand user-specific paths for all users.
|
||||||
|
# this feeds into the symlink cache, so that cached link data can be available no matter which user invokes the program.
|
||||||
|
userPathsClosure = lib.flatten (
|
||||||
|
builtins.map additionalPathsForUser (builtins.attrValues config.users.users)
|
||||||
|
);
|
||||||
|
symlinkCache = {
|
||||||
|
"/bin/sh" = config.environment.binsh;
|
||||||
|
"${builtins.unsafeDiscardStringContext config.environment.binsh}" = "bash";
|
||||||
|
"/usr/bin/env" = config.environment.usrbinenv;
|
||||||
|
"${builtins.unsafeDiscardStringContext config.environment.usrbinenv}" = "coreutils";
|
||||||
|
|
||||||
|
# "/run/current-system" = "${config.system.build.toplevel}";
|
||||||
|
# XXX: /run/current-system symlink can't be cached without forcing regular mass rebuilds:
|
||||||
|
# mount it as if it were a directory instead.
|
||||||
|
"/run/current-system" = "";
|
||||||
|
} // lib.optionalAttrs config.hardware.opengl.enable {
|
||||||
|
"/run/opengl-driver" = let
|
||||||
|
gl = config.hardware.opengl;
|
||||||
|
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/opengl.nix>
|
||||||
|
package = pkgs.buildEnv {
|
||||||
|
name = "opengl-drivers";
|
||||||
|
paths = [ gl.package ] ++ gl.extraPackages;
|
||||||
|
};
|
||||||
|
in "${package}";
|
||||||
|
} // lib.optionalAttrs (config.hardware.opengl.enable && config.hardware.opengl.driSupport32Bit) {
|
||||||
|
"/run/opengl-driver-32" = let
|
||||||
|
gl = config.hardware.opengl;
|
||||||
|
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/opengl.nix>
|
||||||
|
package = pkgs.buildEnv {
|
||||||
|
name = "opengl-drivers-32bit";
|
||||||
|
paths = [ gl.package32 ] ++ gl.extraPackages32;
|
||||||
|
};
|
||||||
|
in "${package}";
|
||||||
|
} // (
|
||||||
|
symlinksToAttrs (symlinksClosure (allowedPaths ++ userPathsClosure))
|
||||||
|
);
|
||||||
|
|
||||||
|
sandboxProfiles = makeProfile {
|
||||||
inherit pkgName;
|
inherit pkgName;
|
||||||
inherit (sandbox)
|
inherit (sandbox)
|
||||||
autodetectCliPaths
|
autodetectCliPaths
|
||||||
@@ -112,41 +147,8 @@ let
|
|||||||
vpn.dns
|
vpn.dns
|
||||||
else
|
else
|
||||||
null;
|
null;
|
||||||
inherit allowedPaths allowedHomePaths allowedRunPaths;
|
inherit allowedPaths allowedHomePaths allowedRunPaths symlinkCache;
|
||||||
|
|
||||||
symlinkCache = {
|
|
||||||
"/bin/sh" = config.environment.binsh;
|
|
||||||
"${builtins.unsafeDiscardStringContext config.environment.binsh}" = "bash";
|
|
||||||
"/usr/bin/env" = config.environment.usrbinenv;
|
|
||||||
"${builtins.unsafeDiscardStringContext config.environment.usrbinenv}" = "coreutils";
|
|
||||||
|
|
||||||
# "/run/current-system" = "${config.system.build.toplevel}";
|
|
||||||
# XXX: /run/current-system symlink can't be cached without forcing regular mass rebuilds:
|
|
||||||
# mount it as if it were a directory instead.
|
|
||||||
"/run/current-system" = "";
|
|
||||||
} // lib.optionalAttrs config.hardware.opengl.enable {
|
|
||||||
"/run/opengl-driver" = let
|
|
||||||
gl = config.hardware.opengl;
|
|
||||||
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/opengl.nix>
|
|
||||||
package = pkgs.buildEnv {
|
|
||||||
name = "opengl-drivers";
|
|
||||||
paths = [ gl.package ] ++ gl.extraPackages;
|
|
||||||
};
|
|
||||||
in "${package}";
|
|
||||||
} // lib.optionalAttrs (config.hardware.opengl.enable && config.hardware.opengl.driSupport32Bit) {
|
|
||||||
"/run/opengl-driver-32" = let
|
|
||||||
gl = config.hardware.opengl;
|
|
||||||
# from: <repo:nixos/nixpkgs:nixos/modules/hardware/opengl.nix>
|
|
||||||
package = pkgs.buildEnv {
|
|
||||||
name = "opengl-drivers-32bit";
|
|
||||||
paths = [ gl.package32 ] ++ gl.extraPackages32;
|
|
||||||
};
|
|
||||||
in "${package}";
|
|
||||||
} // (
|
|
||||||
symlinksToAttrs (symlinksClosure (allowedPaths ++ fullHomePaths ++ fullRunPaths))
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
defaultProfile = sandboxProfilesFor config.sane.defaultUser;
|
|
||||||
makeSandboxedArgs = {
|
makeSandboxedArgs = {
|
||||||
inherit pkgName package;
|
inherit pkgName package;
|
||||||
inherit (sandbox)
|
inherit (sandbox)
|
||||||
@@ -157,13 +159,13 @@ let
|
|||||||
in
|
in
|
||||||
makeSandboxed (makeSandboxedArgs // {
|
makeSandboxed (makeSandboxedArgs // {
|
||||||
passthru = {
|
passthru = {
|
||||||
inherit sandboxProfilesFor;
|
inherit sandboxProfiles;
|
||||||
withEmbeddedSandboxer = makeSandboxed (makeSandboxedArgs // {
|
withEmbeddedSandboxer = makeSandboxed (makeSandboxedArgs // {
|
||||||
# embed the sandboxer AND a profile, whichever profile the package would have if installed by the default user.
|
# embed the sandboxer AND a profile, whichever profile the package would have if installed by the default user.
|
||||||
# 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 = [
|
||||||
"--sanebox-profile-dir" "${defaultProfile}/share/sanebox/profiles"
|
"--sanebox-profile-dir" "${sandboxProfiles}/share/sanebox/profiles"
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
withEmbeddedSandboxerOnly = makeSandboxed (makeSandboxedArgs // {
|
withEmbeddedSandboxerOnly = makeSandboxed (makeSandboxedArgs // {
|
||||||
@@ -566,7 +568,7 @@ let
|
|||||||
# conditionally add to system PATH and env
|
# conditionally add to system PATH and env
|
||||||
environment = lib.optionalAttrs (p.enabled && p.enableFor.system) {
|
environment = lib.optionalAttrs (p.enabled && p.enableFor.system) {
|
||||||
systemPackages = lib.optionals (p.package != null) (
|
systemPackages = lib.optionals (p.package != null) (
|
||||||
[ p.package ] ++ lib.optional (p.sandbox.enable && p.sandbox.method != null) (p.package.passthru.sandboxProfilesFor null)
|
[ p.package ] ++ lib.optional (p.sandbox.enable && p.sandbox.method != null) (p.package.passthru.sandboxProfiles)
|
||||||
);
|
);
|
||||||
# sessionVariables are set by PAM, as opposed to environment.variables which goes in /etc/profile
|
# sessionVariables are set by PAM, as opposed to environment.variables which goes in /etc/profile
|
||||||
sessionVariables = p.env;
|
sessionVariables = p.env;
|
||||||
@@ -575,7 +577,7 @@ let
|
|||||||
# conditionally add to user(s) PATH
|
# conditionally add to user(s) PATH
|
||||||
users.users = lib.mapAttrs (userName: en: {
|
users.users = lib.mapAttrs (userName: en: {
|
||||||
packages = lib.optionals (p.package != null && en && p.enabled) (
|
packages = lib.optionals (p.package != null && en && p.enabled) (
|
||||||
[ p.package ] ++ lib.optional (p.sandbox.enable && p.sandbox.method != null) (p.package.passthru.sandboxProfilesFor userName)
|
[ p.package ] ++ lib.optional (p.sandbox.enable && p.sandbox.method != null) (p.package.passthru.sandboxProfiles)
|
||||||
);
|
);
|
||||||
}) p.enableFor.user;
|
}) p.enableFor.user;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user