From bc47330122c4cbff1058d60fe3894646f641fef5 Mon Sep 17 00:00:00 2001 From: coopi Date: Tue, 9 Jun 2026 12:11:12 +0400 Subject: gnu: services: desktop: Secure kmonad-service-type. This runs the KMonad daemon as a dedicated, unprivileged user, isolates synthetic event creation to a uinput group, and automatically loads the uinput kernel module via udev rules. * gnu/services/desktop.scm (%uinput-group, %kmonad-group, %kmonad-udev-rule) (%kmonad-user, %kmonad-accounts): New variables. (kmonad-shepherd-services): Pass #:user, #:group, and #:supplementary-groups to 'make-forkexec-constructor'. (kmonad-service-type): Extend 'account-service-type' and 'udev-service-type'. Change-Id: Icea21049d0427e25052c952bb08a03379e3a3e1f Signed-off-by: Liliana Marie Prikler --- gnu/services/desktop.scm | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) (limited to 'gnu') diff --git a/gnu/services/desktop.scm b/gnu/services/desktop.scm index 0d0f6d949c2..d4a8878bfd3 100644 --- a/gnu/services/desktop.scm +++ b/gnu/services/desktop.scm @@ -1040,6 +1040,39 @@ screens and scanners."))) @uref{https://github.com/kmonad/kmonad/blob/master/keymap/tutorial.kbd, KMonad - Keymap Tutorial}")) +;; Isolate write access to /dev/uinput to prevent privilege escalation for +;; users/processes that only need read access to the 'input' group. +(define %uinput-group + (user-group + (name "uinput") + (system? #t))) + +(define %kmonad-group + (user-group + (name "kmonad") + (system? #t))) + +;; OPTIONS+="static_node=uinput" triggers kmod to load the uinput module on +;; boot. +(define %kmonad-udev-rule + (udev-rule + "99-kmonad.rules" + "KERNEL==\"uinput\", MODE=\"0660\", GROUP=\"uinput\", OPTIONS+=\"static_node=uinput\"\n")) + +(define %kmonad-user + (user-account + (name "kmonad") + (group "kmonad") + (supplementary-groups '("input" "uinput")) + (system? #t) + (comment "KMonad daemon user") + (home-directory "/var/empty") + (create-home-directory? #f) + (shell (file-append shadow "/sbin/nologin")))) + +(define %kmonad-accounts + (list %uinput-group %kmonad-group %kmonad-user)) + (define (kmonad-shepherd-services config) "Return a shepherd service for each @command{kmonad} configuration." (let* ((kmonad (file-append (kmonad-configuration-kmonad config) @@ -1054,6 +1087,9 @@ screens and scanners."))) (number->string index) ".")) (start #~(make-forkexec-constructor (list #$kmonad "-l" "info" #$keymap) + #:user "kmonad" + #:group "kmonad" + #:supplementary-groups '("input" "uinput") #:log-file #$(string-append "/var/log/" name ".log"))) (stop #~(make-kill-destructor))))) (iota (length keymaps)) @@ -1063,8 +1099,12 @@ screens and scanners."))) (service-type (name 'kmonad) (extensions - (list (service-extension shepherd-root-service-type - kmonad-shepherd-services))) + (list (service-extension account-service-type + (const %kmonad-accounts)) + (service-extension shepherd-root-service-type + kmonad-shepherd-services) + (service-extension udev-service-type + (const (list %kmonad-udev-rule))))) (description "Run the @command{kmonad} daemon, which allows customizing and extending the functionalities of different keyboards."))) -- cgit v1.2.3