[PATCH 4/8] host/rootfs: run xdg-desktop-portal-spectrum-host as non-root

Alyssa Ross
2025-12-10T12:48:34Z

Signed-off-by: Alyssa Ross <hi@alyssa.is>
---
host/rootfs/file-list.mk | 1 +
host/rootfs/image/etc/dbus-portal.conf.in | 11 +++++++++++
.../template/data/service/dbus/run | 8 +++++++-
.../xdg-desktop-portal-spectrum-host/run | 2 ++
host/rootfs/image/usr/bin/run-appimage | 1 +
host/rootfs/image/usr/bin/run-flatpak | 1 +
host/rootfs/image/usr/bin/vm-import | 1 +
host/rootfs/image/usr/bin/vm-start | 19 ++++++++++++++++++-
8 files changed, 42 insertions(+), 2 deletions(-)
create mode 100644 host/rootfs/image/etc/dbus-portal.conf.in

diff --git a/host/rootfs/file-list.mk b/host/rootfs/file-list.mk
index f69775d2..59d83b7e 100644
--- a/host/rootfs/file-list.mk
+++ b/host/rootfs/file-list.mk
@@ -2,6 +2,7 @@
# SPDX-FileCopyrightText: 2025 Demi Marie Obenour <demiobenour@gmail.com>

FILES = \
+ image/etc/dbus-portal.conf.in \
image/etc/fonts/fonts.conf \
image/etc/fstab \
image/etc/init \
diff --git a/host/rootfs/image/etc/dbus-portal.conf.in b/host/rootfs/image/etc/dbus-portal.conf.in
new file mode 100644
index 00000000..3e0e6725
--- /dev/null
+++ b/host/rootfs/image/etc/dbus-portal.conf.in
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- SPDX-FileCopyrightText: 2025 Alyssa Ross <hi@alyssa.is> -->
+
+<busconfig>
+ <include>/usr/share/dbus-1/session.conf</include>
+
+ <policy context="default">
+ <allow user="@XDP_SPECTRUM_USER@"/>
+ </policy>
+</busconfig>
diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/dbus/run b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/dbus/run
index 83e97c65..20f1daff 100755
--- a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/dbus/run
+++ b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/dbus/run
@@ -4,11 +4,17 @@

importas -i VM VM

+if {
+ redirfd -w 1 data/dbus.conf
+ sed "s/@XDP_SPECTRUM_USER@/xdp-spectrum-${VM}/g" /etc/dbus-portal.conf.in
+}
+
s6-ipcserver-socketbinder -B /run/portal-bus/${VM}

fdmove -c 3 0
redirfd -r 0 /dev/null

+getcwd -E dir
nsenter --mount=/run/vm/by-id/${VM}/mount

unshare --cgroup --ipc --net --uts
@@ -17,6 +23,6 @@ export LISTEN_FDS 1
getpid LISTEN_PID

dbus-daemon
- --config-file /usr/share/dbus-1/session.conf
+ --config-file ${dir}/data/dbus.conf
--print-address 4
--address systemd:
diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/xdg-desktop-portal-spectrum-host/run b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/xdg-desktop-portal-spectrum-host/run
index 9e493dff..b83d23dd 100755
--- a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/xdg-desktop-portal-spectrum-host/run
+++ b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/xdg-desktop-portal-spectrum-host/run
@@ -13,4 +13,6 @@ s6-ipcserver-socketbinder -a 0700 /run/vsock/${VM}/vsock_219
if { fdmove 1 3 echo }
fdclose 3

+s6-setuidgid xdp-spectrum-${VM}
+
xdg-desktop-portal-spectrum-host
diff --git a/host/rootfs/image/usr/bin/run-appimage b/host/rootfs/image/usr/bin/run-appimage
index 36f57b85..47cab4c5 100755
--- a/host/rootfs/image/usr/bin/run-appimage
+++ b/host/rootfs/image/usr/bin/run-appimage
@@ -5,6 +5,7 @@
backtick -E dir { mktemp -d /run/vm/by-id/XXXXXX }
backtick -E id { basename -- $dir }
if { useradd -P /run -Urd / -s /bin/nologin gpu-${id} }
+if { useradd -P /run -Urd / -s /bin/nologin xdp-spectrum-${id} }

if { mkdir -p /run/configs/${id}/fs }

diff --git a/host/rootfs/image/usr/bin/run-flatpak b/host/rootfs/image/usr/bin/run-flatpak
index 2ef20433..bb366735 100755
--- a/host/rootfs/image/usr/bin/run-flatpak
+++ b/host/rootfs/image/usr/bin/run-flatpak
@@ -5,6 +5,7 @@
backtick -E dir { mktemp -d /run/vm/by-id/XXXXXX }
backtick -E id { basename -- $dir }
if { useradd -P /run -Urd / -s /bin/nologin gpu-${id} }
+if { useradd -P /run -Urd / -s /bin/nologin xdp-spectrum-${id} }

if {
elgetpositionals
diff --git a/host/rootfs/image/usr/bin/vm-import b/host/rootfs/image/usr/bin/vm-import
index 19a0df36..c848fe32 100755
--- a/host/rootfs/image/usr/bin/vm-import
+++ b/host/rootfs/image/usr/bin/vm-import
@@ -10,6 +10,7 @@ forx -po0 -E name { $names }
backtick -E dir { mktemp -d /run/vm/by-id/XXXXXX }
backtick -E id { basename -- $dir }
if { useradd -P /run -Urd / -s /bin/nologin gpu-${id} }
+if { useradd -P /run -Urd / -s /bin/nologin xdp-spectrum-${id} }

if { ln -s -- ${dir} /run/vm/by-name/${1}.${name} }
if { ln -s -- ${2}/${name} ${dir}/config }
diff --git a/host/rootfs/image/usr/bin/vm-start b/host/rootfs/image/usr/bin/vm-start
index 67480e52..c8031eec 100755
--- a/host/rootfs/image/usr/bin/vm-start
+++ b/host/rootfs/image/usr/bin/vm-start
@@ -20,4 +20,21 @@ foreground {
redirfd -w 2 /dev/null
s6-svwait -U /run/service/vmm/instance/${1}
}
-ch-remote --api-socket /run/vm/by-id/${1}/vmm boot
+foreground { ch-remote --api-socket /run/vm/by-id/${1}/vmm boot }
+importas -Siu ?
+if {
+ if -t { test $? -eq 0 }
+
+ # This is technically racy: if somehow we don't get here before the VM boots
+ # and connects to xdg-desktop-portal-spectrum-host, it won't be able to
+ # connect. The VM rebooting will also break this, because the socket will be
+ # re-created with the wrong mode, but VM reboots are broken anyway at the time
+ # of writing:
+ #
+ # https://github.com/cloud-hypervisor/cloud-hypervisor/issues/7547
+ #
+ # Ideally we'd be able to give a listening socket FD to Cloud Hypervisor for
+ # its VSOCK socket.
+ chown xdp-spectrum-${1} /run/vsock/${1}/vsock
+}
+exit $?
--
2.51.0