aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOphestra Umiker <cat@ophivana.moe>2024-11-06 04:25:15 +0900
committerOphestra Umiker <cat@ophivana.moe>2024-11-06 04:25:15 +0900
commit4d90e733667edc70fb5683b692bb3200055c3a8e (patch)
treefac11b31025dd0e995254845d7762456e0ee564c
parent3dfc1fcd566302a71b9b0f215367c3027139f0fb (diff)
nix: generate strict sandbox configuration
Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
-rw-r--r--nixos.nix230
1 files changed, 179 insertions, 51 deletions
diff --git a/nixos.nix b/nixos.nix
index c04dca71..32fab1fb 100644
--- a/nixos.nix
+++ b/nixos.nix
@@ -15,6 +15,7 @@ let
mapAttrsToList
foldlAttrs
optional
+ optionals
;
cfg = config.environment.fortify;
@@ -39,6 +40,7 @@ in
listOf
attrsOf
nullOr
+ functionTo
;
in
attrsOf (submodule {
@@ -54,6 +56,14 @@ in
launchers = mkOption {
type = attrsOf (submodule {
options = {
+ id = mkOption {
+ type = nullOr str;
+ default = null;
+ description = ''
+ Freedesktop application ID.
+ '';
+ };
+
command = mkOption {
type = nullOr str;
default = null;
@@ -63,17 +73,29 @@ in
'';
};
+ method = mkOption {
+ type = enum [
+ "simple"
+ "sudo"
+ "systemd"
+ ];
+ default = "systemd";
+ description = ''
+ Launch method for the sandboxed program.
+ '';
+ };
+
dbus = {
- config = mkOption {
- type = nullOr anything;
+ session = mkOption {
+ type = nullOr (functionTo anything);
default = null;
description = ''
- D-Bus custom configuration.
+ D-Bus session bus custom configuration.
Setting this to null will enable built-in defaults.
'';
};
- configSystem = mkOption {
+ system = mkOption {
type = nullOr anything;
default = null;
description = ''
@@ -81,24 +103,55 @@ in
Setting this to null will disable the system bus proxy.
'';
};
+ };
- id = mkOption {
- type = nullOr str;
- default = null;
- description = ''
- D-Bus application id.
- Setting this to null will disable own path in defaults.
- Has no effect if custom configuration is set.
- '';
- };
+ env = mkOption {
+ type = nullOr (attrsOf str);
+ default = null;
+ description = ''
+ Environment variables to set for the initial process in the sandbox.
+ '';
+ };
- mpris = mkOption {
- type = bool;
- default = false;
- description = ''
- Whether to enable MPRIS in D-Bus defaults.
- '';
+ nix = mkEnableOption ''
+ Whether to allow nix daemon connections from within sandbox.
+ '';
+
+ userns = mkEnableOption ''
+ Whether to allow userns within sandbox.
+ '';
+
+ useRealUid = mkEnableOption ''
+ Whether to map to fortify's real UID within the sandbox.
+ '';
+
+ net =
+ mkEnableOption ''
+ Whether to allow network access within sandbox.
+ ''
+ // {
+ default = true;
};
+
+ gpu = mkOption {
+ type = nullOr bool;
+ default = null;
+ description = ''
+ Target process GPU and driver access.
+ Setting this to null will enable GPU whenever X or Wayland is enabled.
+ '';
+ };
+
+ dev = mkEnableOption ''
+ Whether to allow access to all devices within sandbox.
+ '';
+
+ extraPaths = mkOption {
+ type = listOf anything;
+ default = [ ];
+ description = ''
+ Extra paths to make available inside the sandbox.
+ '';
};
capability = {
@@ -143,18 +196,6 @@ in
Setting this to null will default package name to wrapper name.
'';
};
-
- method = mkOption {
- type = enum [
- "simple"
- "sudo"
- "systemd"
- ];
- default = "systemd";
- description = ''
- Launch method for the sandboxed program.
- '';
- };
};
});
default = { };
@@ -222,26 +263,113 @@ in
name: launcher:
with launcher.capability;
let
- command = if launcher.command == null then name else launcher.command;
+ extendDBusDefault = id: ext: {
+ filter = true;
+
+ talk = [ "org.freedesktop.Notifications" ] ++ ext.talk;
+ own =
+ (optionals (launcher.id != null) [
+ "${id}.*"
+ "org.mpris.MediaPlayer2.${id}.*"
+ ])
+ ++ ext.own;
+ call = {
+ "org.freedesktop.portal.*" = "*";
+ } // ext.call;
+ broadcast = {
+ "org.freedesktop.portal.*" = "@/org/freedesktop/portal/*";
+ } // ext.broadcast;
+ };
dbusConfig =
- if launcher.dbus.config != null then
- pkgs.writeText "${name}-dbus.json" (builtins.toJSON launcher.dbus.config)
- else
- null;
- dbusSystem =
- if launcher.dbus.configSystem != null then
- pkgs.writeText "${name}-dbus-system.json" (builtins.toJSON launcher.dbus.configSystem)
- else
- null;
- capArgs =
- (if wayland then " --wayland" else "")
- + (if x11 then " -X" else "")
- + (if dbus then " --dbus" else "")
- + (if pulse then " --pulse" else "")
- + (if launcher.dbus.mpris then " --mpris" else "")
- + (if launcher.dbus.id != null then " --dbus-id ${launcher.dbus.id}" else "")
- + (if dbusConfig != null then " --dbus-config ${dbusConfig}" else "")
- + (if dbusSystem != null then " --dbus-system ${dbusSystem}" else "");
+ let
+ default = {
+ talk = [ ];
+ own = [ ];
+ call = { };
+ broadcast = { };
+ };
+ in
+ {
+ session_bus =
+ if launcher.dbus.session != null then
+ (launcher.dbus.session (extendDBusDefault launcher.id))
+ else
+ (extendDBusDefault launcher.id default);
+ system_bus = launcher.dbus.system;
+ };
+ command = if launcher.command == null then name else launcher.command;
+ enablements =
+ (if wayland then 1 else 0)
+ + (if x11 then 2 else 0)
+ + (if dbus then 4 else 0)
+ + (if pulse then 8 else 0);
+ conf = {
+ inherit (launcher) id method;
+ inherit user;
+ command = [
+ "/run/current-system/sw/bin/zsh"
+ (pkgs.writeShellScript "${name}-start" ("exec " + command + " $@"))
+ ];
+ confinement = {
+ sandbox = {
+ inherit (launcher)
+ userns
+ net
+ dev
+ env
+ ;
+ use_real_uid = launcher.useRealUid;
+ filesystem =
+ [
+ { src = "/bin"; }
+ { src = "/usr/bin"; }
+ { src = "/nix/store"; }
+ { src = "/run/current-system"; }
+ {
+ src = "/sys/block";
+ require = false;
+ }
+ {
+ src = "/sys/bus";
+ require = false;
+ }
+ {
+ src = "/sys/class";
+ require = false;
+ }
+ {
+ src = "/sys/dev";
+ require = false;
+ }
+ {
+ src = "/sys/devices";
+ require = false;
+ }
+ {
+ src = "/home/${user}";
+ write = true;
+ require = true;
+ }
+ ]
+ ++ optionals launcher.nix [
+ { src = "/nix/var"; }
+ { src = "/var/db/nix-channels"; }
+ ]
+ ++ optionals (if launcher.gpu != null then launcher.gpu else wayland || x11) [
+ { src = "/run/opengl-driver"; }
+ {
+ src = "/dev/dri";
+ dev = true;
+ }
+ ]
+ ++ launcher.extraPaths;
+ auto_etc = true;
+ override = [ "/var/run/nscd" ];
+ };
+ inherit enablements;
+ inherit (dbusConfig) session_bus system_bus;
+ };
+ };
in
pkgs.writeShellScriptBin name (
if launcher.method == "simple" then
@@ -250,7 +378,7 @@ in
''
else
''
- exec fortify${capArgs} --method ${launcher.method} -u ${user} $SHELL -c "exec ${command} $@"
+ exec fortify app ${pkgs.writeText "fortify-${name}.json" (builtins.toJSON conf)} $@
''
)
) launchers;