Control: merge 1039407 -1
Control: tag -1 + patch

Please find attached two patches for userv. The first one extends the "t-persist" test to try a service user of "root" as well. This turns out to fail when using the existing init script because start-stop-daemon kills the child process that's providing the service.

The second patch provides what I think is a decent systemd unit file for userv. It passes autopkgtest (including the t-persist enhancement mentioned above) and I think is a little nicer than Matthew's one. On the other hand, it's part of the Debian packaging rather than the portable part, (and for instance depends on Debian's symlink from /var/run to /run), so in that respect maybe it's worse.

These patches are also available as git commits in a temporary project on Salsa:

https://salsa.debian.org/bjh21/userv/-/commit/12643dbb0d43c74c540497f02d585781fea45b15
https://salsa.debian.org/bjh21/userv/-/commit/8b10bc740b6027c14156336d486ed684b799056f

--
Ben Harris
From 12643dbb0d43c74c540497f02d585781fea45b15 Mon Sep 17 00:00:00 2001
From: Ben Harris <[email protected]>
Date: Sun, 3 Aug 2025 00:08:48 +0100
Subject: [PATCH 2/5] Run t-persist test with service user as root as well

Services running as root should survive restarts just as well as ones
running as other users.  But I think start-stop-daemon will get this
wrong.
---
 tests/t-persist | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/tests/t-persist b/tests/t-persist
index b886f85..2f4708a 100755
--- a/tests/t-persist
+++ b/tests/t-persist
@@ -3,24 +3,26 @@ set -ex
 
 . tests/lib
 
-coproc userv --override 'execute cat -vet' games spong
+for service_user in games root; do
+    coproc userv --override 'execute cat -vet' "$service_user" spong
 
-stdout=${COPROC[0]}
-stdin=${COPROC[1]}
+    stdout=${COPROC[0]}
+    stdin=${COPROC[1]}
 
-print_expect_reply () {
-    local m=$1
-    local got
-    echo >&$stdin "$m"
-    read <&$stdout got
-    local exp="$(printf '%s$\n' "$m")"
-    test "$got" = "$exp"
-}
+    print_expect_reply () {
+        local m=$1
+        local got
+        echo >&$stdin "$m"
+        read <&$stdout got
+        local exp="$(printf '%s$\n' "$m")"
+        test "$got" = "$exp"
+    }
 
-print_expect_reply hi
+    print_expect_reply hi
 
-service userv restart
+    service userv restart
 
-print_expect_reply ho
+    print_expect_reply ho
+done
 
 echo ok.
-- 
2.39.5

From 8b10bc740b6027c14156336d486ed684b799056f Mon Sep 17 00:00:00 2001
From: Ben Harris <[email protected]>
Date: Thu, 31 Jul 2025 22:12:08 +0100
Subject: [PATCH 4/5] Add systemd unit file

This doesn't use "userv -b shutdown" in ExecStop. systemd.service(5)
documents that ExecStop= commands are required to be synchronous.  That
is, that when the ExecStop= command exits, the service process must have
exited as well.  The userv "shutdown" builtin doesn't have this
property: the connection to the client is closed before the main uservd
process has exited, and so it's possible that the client could exit with
the main uservd still running. Therefore, we must allow systemd to kill
uservd with a signal, which is what the init script does anyway.

uservd is documented to exit with status 1 if it terminates as a result
of SIGTERM.  This is its normal way to exit, so systemd shouldn't treat
it as a failure.

The Description is the one from the init script, and the
documentation includes the specification.
---
 debian/userv.service | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 debian/userv.service

diff --git a/debian/userv.service b/debian/userv.service
new file mode 100644
index 0000000..970c43b
--- /dev/null
+++ b/debian/userv.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=User services (security boundary) daemon
+Documentation=man:uservd(8)
+Documentation=file:/usr/share/doc/userv/spec.html/index.html
+
+[Service]
+Type=forking
+RuntimeDirectory=userv
+RuntimeDirectoryMode=0700
+ExecStart=/usr/sbin/uservd -daemon
+# Don't kill spawned services when killing uservd.
+KillMode=process
+# uservd exits with 1 when killed with SIGTERM.
+SuccessExitStatus=1
+
+[Install]
+WantedBy=multi-user.target
-- 
2.39.5

Reply via email to