[bug#77383,v3,2/3] gnu: speakersafetyd: Run as unprivileged user.

Message ID 140f135aa4f94ad69765f7c2a7b38684342ca382.1744217514.git.roman@burningswell.com
State New
Headers
Series [bug#77383,v3,1/3] gnu: speakersafetyd: Update to 1.1.2. |

Commit Message

Roman Scherer April 9, 2025, 5:26 p.m. UTC
  * gnu/services/sound.scm (speakersafetyd): Run as unprivileged user.

Change-Id: I870bc7bfd69249da3a9c981f627e751395386bd2
---
 doc/guix.texi          |  6 +++++
 gnu/services/sound.scm | 51 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 53 insertions(+), 4 deletions(-)
  

Comments

Maxim Cournoyer April 14, 2025, 6:47 a.m. UTC | #1
Hi Roman,

Roman Scherer <roman@burningswell.com> writes:

> * gnu/services/sound.scm (speakersafetyd): Run as unprivileged user.

I've pushed this series, expounding the GNU ChangeLog commit messages
for completeness.  See 01a66639efe and the subsequent commit for the
commit message additions.  In Magit (emacs-magit), pressing 'C' in each
hunk symbol/thing to document helps automate some of it.
  
Roman Scherer April 14, 2025, 7:30 a.m. UTC | #2
References: <58e6296eb44b3e82e5d6367ae85b681463a38613.1744217514.git.roman@burningswell.com>
	<140f135aa4f94ad69765f7c2a7b38684342ca382.1744217514.git.roman@burningswell.com>
	<87cydfutn3.fsf@gmail.com>
User-Agent: mu4e 1.12.9; emacs 29.4
Hi Maxim,

thanks for your help on this. I will give your magit suggestion a try next
time. I didn't know about that trick.

Thanks Roman.

Date: Mon, 14 Apr 2025 09:30:54 +0200

Maxim Cournoyer <maxim.cournoyer@gmail.com> writes:

> Hi Roman,
>
> Roman Scherer <roman@burningswell.com> writes:
>
>> * gnu/services/sound.scm (speakersafetyd): Run as unprivileged user.
>
> I've pushed this series, expounding the GNU ChangeLog commit messages
> for completeness.  See 01a66639efe and the subsequent commit for the
> commit message additions.  In Magit (emacs-magit), pressing 'C' in each
> hunk symbol/thing to document helps automate some of it.
  

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index bee80cd4e2..6acbf1ba55 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -27267,12 +27267,18 @@  Sound Services
 The base directory as a G-expression (@pxref{G-Expressions}) that
 contains the configuration files of the speaker models.
 
+@item @code{group} (default: @code{"speakersafetyd"}) (type: string)
+The group to run the Speaker Safety Daemon as.
+
 @item @code{maximum-gain-reduction} (default: @code{7}) (type: integer)
 Maximum gain reduction before panicking, useful for debugging.
 
 @item @code{speakersafetyd} (default: @code{speakersafetyd}) (type: file-like)
 The Speaker Safety Daemon package to use.
 
+@item @code{user} (default: @code{"speakersafetyd"}) (type: string)
+The user to run the Speaker Safety Daemon as.
+
 @end table
 @end deftp
 @c %end of fragment
diff --git a/gnu/services/sound.scm b/gnu/services/sound.scm
index fbaa55c553..0558d4fce8 100644
--- a/gnu/services/sound.scm
+++ b/gnu/services/sound.scm
@@ -29,10 +29,12 @@  (define-module (gnu services sound)
   #:use-module (gnu system shadow)
   #:use-module (guix diagnostics)
   #:use-module (guix gexp)
+  #:use-module (guix modules)
   #:use-module (guix packages)
   #:use-module (guix records)
   #:use-module (guix store)
   #:use-module (guix ui)
+  #:use-module (gnu packages admin)
   #:use-module (gnu packages audio)
   #:use-module (gnu packages linux)
   #:use-module (gnu packages pulseaudio)
@@ -288,16 +290,50 @@  (define-configuration/no-serialization speakersafetyd-configuration
    (file-like (file-append speakersafetyd "/share/speakersafetyd"))
    "The base directory as a G-expression (@pxref{G-Expressions}) that contains
 the configuration files of the speaker models.")
+  (group
+   (string "speakersafetyd")
+   "The group to run the Speaker Safety Daemon as.")
   (maximum-gain-reduction
    (integer 7)
    "Maximum gain reduction before panicking, useful for debugging.")
   (speakersafetyd
    (file-like speakersafetyd)
-   "The Speaker Safety Daemon package to use."))
+   "The Speaker Safety Daemon package to use.")
+  (user
+   (string "speakersafetyd")
+   "The user to run the Speaker Safety Daemon as."))
+
+(define speakersafetyd-accounts
+  (match-record-lambda <speakersafetyd-configuration>
+      (group user)
+    (list (user-group
+           (name group)
+           (system? #t))
+          (user-account
+           (name user)
+           (group group)
+           (system? #t)
+           (home-directory "/var/empty")
+           (shell (file-append shadow "/sbin/nologin"))
+           (supplementary-groups '("audio"))))))
+
+(define speakersafetyd-activation
+  (match-record-lambda <speakersafetyd-configuration>
+      (blackbox-directory group user)
+    (with-imported-modules (source-module-closure '((gnu build activation)))
+      #~(begin
+          (use-modules (gnu build activation))
+          (let ((user (getpwnam #$user)))
+            (mkdir-p/perms "/run/speakersafetyd" user #o755)
+            (mkdir-p/perms "/var/lib/speakersafetyd" user #o755)
+            ;; Blackbox files contain audio recordings and might be sensitive
+            ;; information
+            (mkdir-p/perms #$blackbox-directory user #o700))))))
 
 (define speakersafetyd-shepherd-service
   (match-record-lambda <speakersafetyd-configuration>
-      (blackbox-directory configuration-directory maximum-gain-reduction speakersafetyd)
+      ( blackbox-directory configuration-directory group
+        maximum-gain-reduction speakersafetyd user)
     (shepherd-service
      (documentation "Run the speaker safety daemon")
      (provision '(speakersafetyd))
@@ -306,7 +342,10 @@  (define speakersafetyd-shepherd-service
                (list #$(file-append speakersafetyd "/bin/speakersafetyd")
                      "--config-path" #$configuration-directory
                      "--blackbox-path" #$blackbox-directory
-                     "--max-reduction" (number->string #$maximum-gain-reduction))))
+                     "--max-reduction" (number->string #$maximum-gain-reduction))
+               #:group #$group
+               #:supplementary-groups '("audio")
+               #:user #$user))
      (stop #~(make-kill-destructor)))))
 
 (define speakersafetyd-service-type
@@ -324,7 +363,11 @@  (define speakersafetyd-service-type
            (compose list speakersafetyd-configuration-speakersafetyd))
           (service-extension
            profile-service-type
-           (compose list speakersafetyd-configuration-speakersafetyd))))
+           (compose list speakersafetyd-configuration-speakersafetyd))
+          (service-extension account-service-type
+                             speakersafetyd-accounts)
+          (service-extension activation-service-type
+                             speakersafetyd-activation)))
    (default-value (speakersafetyd-configuration))))
 
 ;;; sound.scm ends here