fractal: restrict dbus access a bit tighter
This commit is contained in:
@@ -38,8 +38,15 @@ in
|
||||
|
||||
sandbox.net = "clearnet";
|
||||
sandbox.whitelistAudio = true;
|
||||
sandbox.whitelistDbus.user = true; #< TODO: reduce # notifications
|
||||
sandbox.whitelistDbus.user.own = [ "org.gnome.Fractal" ];
|
||||
sandbox.whitelistDbus.user.call."org.freedesktop.secrets" = "*"; #< TODO: restrict to a subset of secrets
|
||||
sandbox.whitelistDri = true; # otherwise video playback buuuuurns CPU
|
||||
sandbox.whitelistSendNotifications = true;
|
||||
sandbox.whitelistPortal = [
|
||||
"FileChooser"
|
||||
"NetworkMonitor" # if portals are enabled, but NetworkMonitor *isn't*, then it'll hang on launch
|
||||
"OpenURI"
|
||||
];
|
||||
sandbox.whitelistWayland = true;
|
||||
sandbox.extraHomePaths = [
|
||||
# still needs these paths despite it using the portal's file-chooser :?
|
||||
|
@@ -107,14 +107,10 @@ let
|
||||
null;
|
||||
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
|
||||
(interface: lib.map (methodSpec: "${interface}=${methodSpec}"))
|
||||
sandbox.whitelistDbus.user.call
|
||||
);
|
||||
allowedDbusOwn = sandbox.whitelistDbus.user.own;
|
||||
# the sandboxer knows how to work with duplicated paths, but they're still annoying => `lib.unique`
|
||||
allowedPaths = lib.unique allowedPaths;
|
||||
allowedHomePaths = lib.unique allowedHomePaths;
|
||||
@@ -460,36 +456,44 @@ let
|
||||
pipewire-aware applications shouldn't need this.
|
||||
'';
|
||||
};
|
||||
sandbox.whitelistDbus.user = let
|
||||
dbusInterfaceModule = types.submodule {
|
||||
sandbox.whitelistDbus.user = mkOption {
|
||||
type = types.coercedTo
|
||||
types.bool (b: { all = b; })
|
||||
(types.submodule {
|
||||
options = {
|
||||
own = mkOption {
|
||||
all = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
allow the sandbox to own this well-defined name.
|
||||
allow full, unrestricted dbus access
|
||||
'';
|
||||
};
|
||||
own = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
allow the sandbox to own any well-known name in this list.
|
||||
'';
|
||||
};
|
||||
call = mkOption {
|
||||
type = types.coercedTo types.str (s: [ s ]) (types.listOf types.str);
|
||||
default = [];
|
||||
type = types.attrsOf (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.
|
||||
for each attribute name, allow the sandbox to call methods on that well-known bus name
|
||||
so long as they satisfy the specifier encoded in the attribute value.
|
||||
|
||||
e.g. { "org.freedesktop.portal" = [ "org.freedesktop.portal.FileChooser.*"; ]; };
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
in mkOption {
|
||||
type = types.coercedTo
|
||||
types.bool (b: lib.optionalAttrs b { "*".own = true; })
|
||||
(types.attrsOf dbusInterfaceModule);
|
||||
})
|
||||
;
|
||||
default = {};
|
||||
description = ''
|
||||
allow sandbox to selectively interact with user dbus services.
|
||||
e.g. {
|
||||
"org.gnome.Calls".own = true;
|
||||
"org.freedesktop.portal".call = "org.freedesktop.portal.FileChooser.*";
|
||||
own = [ "org.gnome.Calls" ];
|
||||
call."org.freedesktop.portal" = "org.freedesktop.portal.FileChooser.*";
|
||||
};
|
||||
special `*` path can be used to allow ALL user dbus traffic:
|
||||
e.g. {
|
||||
@@ -516,6 +520,35 @@ let
|
||||
broad and unaudited attack surface.
|
||||
'';
|
||||
};
|
||||
sandbox.whitelistPortal = mkOption {
|
||||
type = types.listOf (types.enum [
|
||||
# "Account"
|
||||
# "Camera"
|
||||
# "Device"
|
||||
"DynamicLauncher"
|
||||
# "Email"
|
||||
"FileChooser"
|
||||
# "GameMode"
|
||||
"Location"
|
||||
# "MemoryMonitor"
|
||||
"NetworkMonitor" # bleh!
|
||||
"Notification"
|
||||
"OpenURI"
|
||||
# "PowerProfileMonitor"
|
||||
# "Print"
|
||||
# "ProxyResolver"
|
||||
# "Realtime"
|
||||
# "ScreenCast"
|
||||
# "Screenshot"
|
||||
# "Settings"
|
||||
# "Trash"
|
||||
# "Wallpaper"
|
||||
]);
|
||||
default = [];
|
||||
description = ''
|
||||
allow calling specific interfaces under org.freedesktop.portal
|
||||
'';
|
||||
};
|
||||
sandbox.whitelistPwd = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
@@ -530,6 +563,14 @@ let
|
||||
allow the program to start/stop s6 services.
|
||||
'';
|
||||
};
|
||||
sandbox.whitelistSendNotifications = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
allow the program to send notifications to the desktop manager (like `notify-send`).
|
||||
typically works via dbus.
|
||||
'';
|
||||
};
|
||||
sandbox.whitelistSystemctl = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
@@ -660,6 +701,22 @@ let
|
||||
|
||||
sandbox.whitelistDbus.system = lib.mkIf config.sandbox.whitelistSystemctl true;
|
||||
|
||||
sandbox.whitelistDbus.user.call = lib.mkMerge ([
|
||||
(lib.mkIf config.sandbox.whitelistSendNotifications {
|
||||
"org.freedesktop.Notifications" = "*"; # Notify, NotificationClosed, NotificationReplied, ActionInvoked
|
||||
"org.erikreider.swaync.cc" = "*"; #< probably overkill
|
||||
})
|
||||
] ++ lib.forEach config.sandbox.whitelistPortal (p: {
|
||||
"org.freedesktop.portal.Desktop" = [
|
||||
"org.freedesktop.portal.${p}.*"
|
||||
# "org.freedesktop.DBus.Peer" #< seems to not be needed
|
||||
# "org.freedesktop.DBus.Properties"
|
||||
# "org.freedesktop.DBus.Introspectable"
|
||||
];
|
||||
}));
|
||||
|
||||
sandbox.whitelistPortal = lib.mkIf config.sandbox.whitelistSendNotifications [ "Notification" ];
|
||||
|
||||
sandbox.extraEnv = {
|
||||
MESA_SHADER_CACHE_DIR = lib.mkIf (config.sandbox.mesaCacheDir != null) "$HOME/${config.sandbox.mesaCacheDir}";
|
||||
TMPDIR = lib.mkIf (config.sandbox.tmpDir != null) "$HOME/${config.sandbox.tmpDir}";
|
||||
@@ -748,7 +805,7 @@ let
|
||||
;
|
||||
sandbox.extraRuntimePaths =
|
||||
lib.optionals config.sandbox.whitelistAudio [ "pipewire" "pulse" ] # this includes pipewire/pipewire-0-manager: is that ok?
|
||||
++ lib.optionals ((config.sandbox.whitelistDbus.user."*" or {}).own or false) [ "dbus" ]
|
||||
++ lib.optionals config.sandbox.whitelistDbus.user.all [ "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!
|
||||
;
|
||||
|
Reference in New Issue
Block a user