From 37e6624667091ad729ad2691773ae053444c5b2b Mon Sep 17 00:00:00 2001 From: Lin Jian Date: Thu, 2 Jan 2025 10:26:06 +0800 Subject: [PATCH] nixos/kmonad: add new option enableHardening MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before ```console $ systemd-analyze security kmonad-foo.service | tail -n 1 → Overall exposure level for kmonad-foo.service: 8.2 EXPOSED 🙁 ``` After ```console $ systemd-analyze security kmonad-foo.service | tail -n 1 → Overall exposure level for kmonad-foo.service: 0.4 SAFE 😀 ``` --- .../manual/release-notes/rl-2505.section.md | 3 + nixos/modules/services/hardware/kmonad.nix | 87 ++++++++++++++----- 2 files changed, 70 insertions(+), 20 deletions(-) diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 0295deffc3d00..65e1e0421fc15 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -126,6 +126,9 @@ to review the new defaults and description of [](#opt-services.nextcloud.poolSettings). +- `kmonad` is now hardened by default using common `systemd` settings. + If KMonad is used to execute shell commands, hardening may make some of them fail. In that case, you can disable hardening using {option}`services.kmonad.keyboards..enableHardening` option. + - `asusd` has been upgraded to version 6 which supports multiple aura devices. To account for this, the single `auraConfig` configuration option has been replaced with `auraConfigs` which is an attribute set of config options per each device. The config files may also be now specified as either source files or text strings; to account for this you will need to specify that `text` is used for your existing configs, e.g.: ```diff -services.asusd.asusdConfig = '''file contents''' diff --git a/nixos/modules/services/hardware/kmonad.nix b/nixos/modules/services/hardware/kmonad.nix index fa9b8fbb610f5..72d5d7d71503c 100644 --- a/nixos/modules/services/hardware/kmonad.nix +++ b/nixos/modules/services/hardware/kmonad.nix @@ -41,6 +41,19 @@ let ''; }; + enableHardening = lib.mkOption { + type = lib.types.bool; + default = true; + example = false; + description = '' + Whether to enable systemd hardening. + + ::: {.note} + If KMonad is used to execute shell commands, hardening may make some of them fail. + ::: + ''; + }; + defcfg = { enable = lib.mkEnableOption '' automatic generation of the defcfg block. @@ -128,26 +141,60 @@ let StartLimitIntervalSec = 2; StartLimitBurst = 5; }; - serviceConfig = { - ExecStart = '' - ${lib.getExe cfg.package} ${mkCfg keyboard} \ - ${utils.escapeSystemdExecArgs cfg.extraArgs} - ''; - Restart = "always"; - # Restart at increasing intervals from 2s to 1m - RestartSec = 2; - RestartSteps = 30; - RestartMaxDelaySec = "1min"; - Nice = -20; - DynamicUser = true; - User = "kmonad"; - Group = "kmonad"; - SupplementaryGroups = [ - # These ensure that our dynamic user has access to the device node - config.users.groups.input.name - config.users.groups.uinput.name - ] ++ keyboard.extraGroups; - }; + serviceConfig = + { + ExecStart = '' + ${lib.getExe cfg.package} ${mkCfg keyboard} \ + ${utils.escapeSystemdExecArgs cfg.extraArgs} + ''; + Restart = "always"; + # Restart at increasing intervals from 2s to 1m + RestartSec = 2; + RestartSteps = 30; + RestartMaxDelaySec = "1min"; + Nice = -20; + DynamicUser = true; + User = "kmonad"; + Group = "kmonad"; + SupplementaryGroups = [ + # These ensure that our dynamic user has access to the device node + config.users.groups.input.name + config.users.groups.uinput.name + ] ++ keyboard.extraGroups; + } + // lib.optionalAttrs keyboard.enableHardening { + DeviceAllow = [ + "/dev/uinput w" + "char-input r" + ]; + CapabilityBoundingSet = [ "" ]; + DevicePolicy = "closed"; + IPAddressDeny = [ "any" ]; + LockPersonality = true; + MemoryDenyWriteExecute = true; + PrivateNetwork = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + RestrictAddressFamilies = [ "none" ]; + RestrictNamespaces = true; + RestrictRealtime = true; + SystemCallArchitectures = [ "native" ]; + SystemCallErrorNumber = "EPERM"; + SystemCallFilter = [ + "@system-service" + "~@privileged" + "~@resources" + ]; + UMask = "0077"; + }; # make sure the new config is used after nixos-rebuild switch # stopIfChanged controls[0] how a service is "restarted" during # nixos-rebuild switch. By default, stopIfChanged is true, which stops