programs: refactor whitelistDbus

This commit is contained in:
2025-01-06 09:23:06 +00:00
parent 365d9c2457
commit 2a1d6fff08
83 changed files with 171 additions and 151 deletions

View File

@@ -76,7 +76,7 @@ let
"/run/systemd/resolve" #< to allow reading /etc/resolv.conf, which ultimately symlinks here (if using systemd-resolved)
] ++ lib.optionals (sandbox.net == "all" && config.services.avahi.enable) [
"/var/run/avahi-daemon" #< yes, it has to be "/var/run/...". required for nss (e.g. `getent hosts desko.local`)
] ++ lib.optionals (builtins.elem "system" sandbox.whitelistDbus) [
] ++ lib.optionals sandbox.whitelistDbus.system [
"/var/run/dbus/system_bus_socket" #< XXX: use /var/run/..., for the rare program which requires that (i.e. avahi users)
] ++ sandbox.extraPaths
;
@@ -105,7 +105,17 @@ let
vpn.dns
else
null;
# the sandboxer should understand how to work with duplicated paths, but it's annoying => `lib.unique`
allowedDbusCall = lib.flatten (
lib.mapAttrsToList
(interface: value: lib.map (callSpec: "${interface}=${callSpec}") value.call)
sandbox.whitelistDbus.user
);
allowedDbusOwn = lib.flatten (
lib.mapAttrsToList
(interface: value: lib.optional value.own interface)
sandbox.whitelistDbus.user
);
# the sandboxer knows how to work with duplicated paths, but they're still annoying => `lib.unique`
allowedPaths = lib.unique allowedPaths;
allowedHomePaths = lib.unique allowedHomePaths;
allowedRunPaths = lib.unique allowedRunPaths;
@@ -288,7 +298,7 @@ let
depends = svcCfg.depends
++ lib.optionals (((config.persist.byStore or {}).private or []) != []) [
"private-storage"
] ++ lib.optionals (svcName != "dbus-user" && builtins.elem "user" config.sandbox.whitelistDbus && cfg.dbus.enabled) [
] ++ lib.optionals (svcName != "dbus-user" && config.sandbox.whitelistDbus.user != {} && cfg.dbus.enabled) [
"dbus-user"
] ++ lib.optionals ((!builtins.elem "wayland" svcCfg.partOf) && config.sandbox.whitelistWayland) [
"wayland"
@@ -450,11 +460,49 @@ let
pipewire-aware applications shouldn't need this.
'';
};
sandbox.whitelistDbus = mkOption {
type = types.listOf (types.enum [ "user" "system" ]);
default = [ ];
sandbox.whitelistDbus.user = let
dbusInterfaceModule = types.submodule {
options = {
own = mkOption {
type = types.bool;
default = false;
description = ''
allow the sandbox to own this well-defined name.
'';
};
call = mkOption {
type = types.coercedTo types.str (s: [ s ]) (types.listOf types.str);
default = [];
description = ''
allow the sandbox to call methods on this well-defined name
so long as they this method specifier.
'';
};
};
};
in mkOption {
type = types.coercedTo
types.bool (b: lib.optionalAttrs b { "*".own = true; })
(types.attrsOf dbusInterfaceModule);
default = {};
description = ''
allow sandbox to freely interact with dbus services.
allow sandbox to selectively interact with user dbus services.
e.g. {
"org.gnome.Calls".own = true;
"org.freedesktop.portal".call = "org.freedesktop.portal.FileChooser.*";
};
special `*` path can be used to allow ALL user dbus traffic:
e.g. {
"*".call = true;
"*".own = true;
}
'';
};
sandbox.whitelistDbus.system = mkOption {
type = types.bool;
default = false;
description = ''
allow sandbox to freely interact with system dbus services.
'';
};
sandbox.whitelistDri = mkOption {
@@ -610,7 +658,7 @@ let
sandbox.keepPids = lib.mkIf config.sandbox.keepPidsAndProc true;
sandbox.whitelistDbus = lib.mkIf config.sandbox.whitelistSystemctl [ "system" ];
sandbox.whitelistDbus.system = lib.mkIf config.sandbox.whitelistSystemctl true;
sandbox.extraEnv = {
MESA_SHADER_CACHE_DIR = lib.mkIf (config.sandbox.mesaCacheDir != null) "$HOME/${config.sandbox.mesaCacheDir}";
@@ -700,7 +748,7 @@ let
;
sandbox.extraRuntimePaths =
lib.optionals config.sandbox.whitelistAudio [ "pipewire" "pulse" ] # this includes pipewire/pipewire-0-manager: is that ok?
++ lib.optionals (builtins.elem "user" config.sandbox.whitelistDbus) [ "dbus" ]
++ lib.optionals ((config.sandbox.whitelistDbus.user."*" or {}).own or false) [ "dbus" ]
++ lib.optionals config.sandbox.whitelistWayland [ "wl" ] # app can still communicate with wayland server w/o this, if it has net access
++ lib.optionals config.sandbox.whitelistS6 [ "s6" ] # TODO: this allows re-writing the services themselves: don't allow that!
;

View File

@@ -3,6 +3,8 @@ let
bunpenGenerators = {
autodetectCliPaths = style: [ "--bunpen-autodetect" style ];
capability = cap: [ "--bunpen-cap" cap ];
dbusCall = spec: [ "--bunpen-dbus-call" spec ];
dbusOwn = interface: [ "--bunpen-dbus-own" interface ];
dns = addr: [ "--bunpen-dns" addr ];
env = key: value: [ "--bunpen-env" "${key}=${value}" ];
keepIpc = [ "--bunpen-keep-ipc" ];
@@ -40,6 +42,8 @@ let
in
{
method,
allowedDbusCall ? [],
allowedDbusOwn ? [],
allowedPaths ? [],
allowedHomePaths ? [],
allowedRunPaths ? [],
@@ -67,6 +71,10 @@ let
envArgs = lib.flatten (lib.mapAttrsToList gen.env extraEnv);
dbusItems = lib.flatten (lib.map gen.dbusOwn allowedDbusOwn)
++ lib.flatten (lib.map gen.dbusCall allowedDbusCall)
;
netItems = lib.optionals (netDev != null) (gen.netDev netDev)
++ lib.optionals (netGateway != null) (gen.netGateway netGateway)
++ lib.optionals (dns != null) (lib.flatten (builtins.map gen.dns dns))
@@ -74,6 +82,7 @@ let
in
(gen.method method)
++ dbusItems
++ netItems
++ allowPaths "unqualified" allowedPaths
++ allowPaths "home" allowedHomePaths