Control: merge 1039407 -1 Control: tag -1 + patchPlease 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

