[PATCH 1/8] host/rootfs: create dbus socket externally
This is the first step towards running dbus as non-root. Signed-off-by: Alyssa Ross <hi@alyssa.is> --- .../template/data/service/dbus/notification-fd | 2 +- .../data/service/dbus/notification-fd.license | 2 +- .../vm-services/template/data/service/dbus/run | 13 +++++++++++-- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/dbus/notification-fd b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/dbus/notification-fd index 00750edc..b8626c4c 100644 --- a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/dbus/notification-fd +++ b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/dbus/notification-fd @@ -1 +1 @@ -3 +4 diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/dbus/notification-fd.license b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/dbus/notification-fd.license index 5a406331..0d3d47ca 100644 --- a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/dbus/notification-fd.license +++ b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/dbus/notification-fd.license @@ -1,2 +1,2 @@ SPDX-License-Identifier: CC0-1.0 -SPDX-FileCopyrightText: 2022 Alyssa Ross <hi@alyssa.is> +SPDX-FileCopyrightText: 2025 Alyssa Ross <hi@alyssa.is> 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 40b75355..365e1697 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,10 +4,19 @@ importas -i VM VM +s6-ipcserver-socketbinder -B /run/vm/by-id/${VM}/portal-bus + +fdmove -c 3 0 +redirfd -r 0 /dev/null + nsenter --mount=/run/vm/by-id/${VM}/mount unshare --cgroup --ipc --net --uts + +export LISTEN_FDS 1 +getpid LISTEN_PID + dbus-daemon --config-file /usr/share/dbus-1/session.conf - --print-address 3 - --address unix:path=/run/vm/by-id/${VM}/portal-bus + --print-address 4 + --address systemd: -- 2.51.0
This will allow xdg-desktop-portal-spectrum-host to be run as a user without access to the VM directory. Signed-off-by: Alyssa Ross <hi@alyssa.is> --- .../template/data/service/xdg-desktop-portal-spectrum-host/run | 3 ++- tools/start-vmm/lib.rs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) 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 d2bf78ce..57e893d3 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 @@ -6,7 +6,8 @@ importas -i VM VM export DBUS_SESSION_BUS_ADDRESS unix:path=/run/vm/by-id/${VM}/portal-bus -s6-ipcserver-socketbinder -a 0700 /run/vm/by-id/${VM}/vsock_219 +if { mkdir -p /run/vsock/${VM} } +s6-ipcserver-socketbinder -a 0700 /run/vsock/${VM}/vsock_219 # Notify readiness. if { fdmove 1 3 echo } diff --git a/tools/start-vmm/lib.rs b/tools/start-vmm/lib.rs index b44e0375..52c96c5e 100644 --- a/tools/start-vmm/lib.rs +++ b/tools/start-vmm/lib.rs @@ -154,7 +154,7 @@ pub fn vm_config(vm_dir: &Path) -> Result<VmConfig, String> { }, vsock: VsockConfig { cid: 3, - socket: vm_dir.join("vsock").into_os_string().into_string().unwrap(), + socket: format!("/run/vsock/{vm_name}/vsock"), }, landlock_enable: true, landlock_rules: vec![ -- 2.51.0
This will allow xdg-desktop-portal-spectrum-host to be run as a user without access to the VM directory. Signed-off-by: Alyssa Ross <hi@alyssa.is> --- host/rootfs/Makefile | 1 + .../service/vm-services/template/data/service/dbus/run | 2 +- .../template/data/service/xdg-desktop-portal-spectrum-host/run | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/host/rootfs/Makefile b/host/rootfs/Makefile index 7bec1259..b9e0fdd9 100644 --- a/host/rootfs/Makefile +++ b/host/rootfs/Makefile @@ -14,6 +14,7 @@ DIRS = \ dev \ etc/s6-linux-init/env \ etc/s6-linux-init/run-image/configs \ + etc/s6-linux-init/run-image/portal-bus \ etc/s6-linux-init/run-image/sd-notify-wrapper \ etc/s6-linux-init/run-image/service/serial-getty/instance \ etc/s6-linux-init/run-image/service/serial-getty/instances \ 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 365e1697..83e97c65 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,7 +4,7 @@ importas -i VM VM -s6-ipcserver-socketbinder -B /run/vm/by-id/${VM}/portal-bus +s6-ipcserver-socketbinder -B /run/portal-bus/${VM} fdmove -c 3 0 redirfd -r 0 /dev/null 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 57e893d3..9e493dff 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 @@ -4,7 +4,7 @@ importas -i VM VM -export DBUS_SESSION_BUS_ADDRESS unix:path=/run/vm/by-id/${VM}/portal-bus +export DBUS_SESSION_BUS_ADDRESS unix:path=/run/portal-bus/${VM} if { mkdir -p /run/vsock/${VM} } s6-ipcserver-socketbinder -a 0700 /run/vsock/${VM}/vsock_219 -- 2.51.0
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-License-Identifier: CC0-1.0 --> +<!-- SPDX-FileCopyrightText: 2025 Alyssa Ross <hi@alyssa.is> --> +<!DOCTYPE busconfig SYSTEM "busconfig.dtd"> +<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
On 12/10/25 07:47, Alyssa Ross wrote:
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-License-Identifier: CC0-1.0 --> +<!-- SPDX-FileCopyrightText: 2025 Alyssa Ross <hi@alyssa.is> --> +<!DOCTYPE busconfig SYSTEM "busconfig.dtd"> +<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 +}
This makes me nervous. I know that $VM is trusted, but I'd feel better if this was validated with a case command. There's a bug in case that makes this not work properly, but that's fixed in execline git right now.
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:
(snip)
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
It's possible to avoid the race using extended ACLs.
+} +exit $? -- Sincerely, Demi Marie Obenour (she/her/hers)
Demi Marie Obenour <demiobenour@gmail.com> writes:
On 12/10/25 07:47, Alyssa Ross wrote:
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-License-Identifier: CC0-1.0 --> +<!-- SPDX-FileCopyrightText: 2025 Alyssa Ross <hi@alyssa.is> --> +<!DOCTYPE busconfig SYSTEM "busconfig.dtd"> +<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 +}
This makes me nervous. I know that $VM is trusted, but I'd feel better if this was validated with a case command. There's a bug in case that makes this not work properly, but that's fixed in execline git right now.
I don't think this is necessary, because as you say it's trusted. There shouldn't be any way to invoke this script with elevated permissions anyway, so it's not doing anything that whatever is invoking it couldn't just do themself.
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
It's possible to avoid the race using extended ACLs.
Nice idea!
Alyssa Ross <hi@alyssa.is> writes:
Demi Marie Obenour <demiobenour@gmail.com> writes:
On 12/10/25 07:47, Alyssa Ross wrote:
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
It's possible to avoid the race using extended ACLs.
Nice idea!
Actually I don't think it is, sadly. Even with acls like the following, when Cloud Hypervisor creates its socket, the mask ends up getting set to ---, so xdp-spectrum-host still can't connect. See also[1]. # file: run/vsock/GeOkfl # owner: root # group: root user::rwx group::r-x other::r-x default:user::rwx default:user:xdp-spectrum-GeOkfl:rwx default:group::r-x default:mask::rwx default:other::r-x Even making the directory setgid wouldn't help, because the effective mask applies to /all/ groups. I don't think there's a way to do this at the moment without either setting a less restrictive umask on Cloud Hypervisor, or the approach I sent here. [1]: https://serverfault.com/questions/833349/why-is-my-unix-socket-created-with-...
On 12/11/25 07:19, Alyssa Ross wrote:
Demi Marie Obenour <demiobenour@gmail.com> writes:
On 12/10/25 07:47, Alyssa Ross wrote:
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-License-Identifier: CC0-1.0 --> +<!-- SPDX-FileCopyrightText: 2025 Alyssa Ross <hi@alyssa.is> --> +<!DOCTYPE busconfig SYSTEM "busconfig.dtd"> +<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 +}
This makes me nervous. I know that $VM is trusted, but I'd feel better if this was validated with a case command. There's a bug in case that makes this not work properly, but that's fixed in execline git right now.
I don't think this is necessary, because as you say it's trusted. There shouldn't be any way to invoke this script with elevated permissions anyway, so it's not doing anything that whatever is invoking it couldn't just do themself.
It's more that I prefer to avoid unnecessary places where bad input can lead to code execution. Using awk to substitute would also make this easy. -- Sincerely, Demi Marie Obenour (she/her/hers)
The document portal has to be root to mount its fuse filesystem. This needs to be a shared namespace because virtiofsd needs to be in the same mount namespace as the document portal so that it sees the fuse filesystem, so we create a per-VM persistent user namespace. Signed-off-by: Alyssa Ross <hi@alyssa.is> --- host/rootfs/image/usr/bin/create-vm-dependencies | 9 +++++++-- host/rootfs/image/usr/bin/run-appimage | 2 ++ host/rootfs/image/usr/bin/run-flatpak | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/host/rootfs/image/usr/bin/create-vm-dependencies b/host/rootfs/image/usr/bin/create-vm-dependencies index d4a10ab4..7ce19ed2 100755 --- a/host/rootfs/image/usr/bin/create-vm-dependencies +++ b/host/rootfs/image/usr/bin/create-vm-dependencies @@ -2,8 +2,9 @@ # SPDX-License-Identifier: EUPL-1.2+ # SPDX-FileCopyrightText: 2024-2025 Alyssa Ross <hi@alyssa.is> -if { touch /run/vm/by-id/${1}/mount } +if { touch /run/vm/by-id/${1}/mount /run/vm/by-id/${1}/user } if { mount --make-private --bind /run/vm/by-id/${1}/mount /run/vm/by-id/${1}/mount } +if { mount --make-private --bind /run/vm/by-id/${1}/user /run/vm/by-id/${1}/user } if { mkdir -p @@ -13,7 +14,11 @@ if { } if { - unshare --propagation=slave --mount=/run/vm/by-id/${1}/mount + unshare --propagation=slave + --map-users all + --map-groups all + --mount=/run/vm/by-id/${1}/mount + --user=/run/vm/by-id/${1}/user if { mount --make-shared --rbind /run/vm/by-id/${1} /run/vm/by-id/${1} } diff --git a/host/rootfs/image/usr/bin/run-appimage b/host/rootfs/image/usr/bin/run-appimage index 47cab4c5..5e8e29fa 100755 --- a/host/rootfs/image/usr/bin/run-appimage +++ b/host/rootfs/image/usr/bin/run-appimage @@ -44,4 +44,6 @@ if { s6-instance-delete /run/service/vm-services $id } if { umount ${dir}/mount } # mount namespace if { umount ${dir}/mount } # private bind mount +if { umount ${dir}/user } # user namespace +if { umount ${dir}/user } # private bind mount rm -r $dir /run/configs/${id} diff --git a/host/rootfs/image/usr/bin/run-flatpak b/host/rootfs/image/usr/bin/run-flatpak index bb366735..86ccc12a 100755 --- a/host/rootfs/image/usr/bin/run-flatpak +++ b/host/rootfs/image/usr/bin/run-flatpak @@ -46,4 +46,6 @@ if { s6-instance-delete -- /run/service/vm-services $id } if { umount ${dir}/mount } # mount namespace if { umount ${dir}/mount } # private bind mount +if { umount ${dir}/user } # user namespace +if { umount ${dir}/user } # private bind mount rm -r $dir /run/configs/${id} -- 2.51.0
On 12/10/25 07:47, Alyssa Ross wrote:
The document portal has to be root to mount its fuse filesystem. This needs to be a shared namespace because virtiofsd needs to be in the same mount namespace as the document portal so that it sees the fuse filesystem, so we create a per-VM persistent user namespace.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
(snip)
diff --git a/host/rootfs/image/usr/bin/run-appimage b/host/rootfs/image/usr/bin/run-appimage index 47cab4c5..5e8e29fa 100755 --- a/host/rootfs/image/usr/bin/run-appimage +++ b/host/rootfs/image/usr/bin/run-appimage @@ -44,4 +44,6 @@ if { s6-instance-delete /run/service/vm-services $id }
if { umount ${dir}/mount } # mount namespace if { umount ${dir}/mount } # private bind mount +if { umount ${dir}/user } # user namespace +if { umount ${dir}/user } # private bind mount rm -r $dir /run/configs/${id} diff --git a/host/rootfs/image/usr/bin/run-flatpak b/host/rootfs/image/usr/bin/run-flatpak index bb366735..86ccc12a 100755 --- a/host/rootfs/image/usr/bin/run-flatpak +++ b/host/rootfs/image/usr/bin/run-flatpak @@ -46,4 +46,6 @@ if { s6-instance-delete -- /run/service/vm-services $id }
if { umount ${dir}/mount } # mount namespace if { umount ${dir}/mount } # private bind mount +if { umount ${dir}/user } # user namespace +if { umount ${dir}/user } # private bind mount rm -r $dir /run/configs/${id}
Why is it necessary to unmount twice here? -- Sincerely, Demi Marie Obenour (she/her/hers)
Demi Marie Obenour <demiobenour@gmail.com> writes:
On 12/10/25 07:47, Alyssa Ross wrote:
The document portal has to be root to mount its fuse filesystem. This needs to be a shared namespace because virtiofsd needs to be in the same mount namespace as the document portal so that it sees the fuse filesystem, so we create a per-VM persistent user namespace.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
(snip)
diff --git a/host/rootfs/image/usr/bin/run-appimage b/host/rootfs/image/usr/bin/run-appimage index 47cab4c5..5e8e29fa 100755 --- a/host/rootfs/image/usr/bin/run-appimage +++ b/host/rootfs/image/usr/bin/run-appimage @@ -44,4 +44,6 @@ if { s6-instance-delete /run/service/vm-services $id }
if { umount ${dir}/mount } # mount namespace if { umount ${dir}/mount } # private bind mount +if { umount ${dir}/user } # user namespace +if { umount ${dir}/user } # private bind mount rm -r $dir /run/configs/${id} diff --git a/host/rootfs/image/usr/bin/run-flatpak b/host/rootfs/image/usr/bin/run-flatpak index bb366735..86ccc12a 100755 --- a/host/rootfs/image/usr/bin/run-flatpak +++ b/host/rootfs/image/usr/bin/run-flatpak @@ -46,4 +46,6 @@ if { s6-instance-delete -- /run/service/vm-services $id }
if { umount ${dir}/mount } # mount namespace if { umount ${dir}/mount } # private bind mount +if { umount ${dir}/user } # user namespace +if { umount ${dir}/user } # private bind mount rm -r $dir /run/configs/${id}
Why is it necessary to unmount twice here?
Because we mount twice, just like the comments say. It is a bit counterintuitive though. Namespaces can only be mounted onto a mountpoint that itself has private propagation. This is why we create a private bind mount at the start of create-vm-dependencies before unshare bind mounts the namespaces. You can also see this in an example in unshare(1). Perhaps it would be better and clearer to have /run/vm/by-id/${VM}/ns as a private mountpoint, with the nsfs files inside? That way, each of them only needs to be unmounted once, and then the ns directory also has to be unmounted once.
On 12/11/25 07:41, Alyssa Ross wrote:
Demi Marie Obenour <demiobenour@gmail.com> writes:
On 12/10/25 07:47, Alyssa Ross wrote:
The document portal has to be root to mount its fuse filesystem. This needs to be a shared namespace because virtiofsd needs to be in the same mount namespace as the document portal so that it sees the fuse filesystem, so we create a per-VM persistent user namespace.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
(snip)
diff --git a/host/rootfs/image/usr/bin/run-appimage b/host/rootfs/image/usr/bin/run-appimage index 47cab4c5..5e8e29fa 100755 --- a/host/rootfs/image/usr/bin/run-appimage +++ b/host/rootfs/image/usr/bin/run-appimage @@ -44,4 +44,6 @@ if { s6-instance-delete /run/service/vm-services $id }
if { umount ${dir}/mount } # mount namespace if { umount ${dir}/mount } # private bind mount +if { umount ${dir}/user } # user namespace +if { umount ${dir}/user } # private bind mount rm -r $dir /run/configs/${id} diff --git a/host/rootfs/image/usr/bin/run-flatpak b/host/rootfs/image/usr/bin/run-flatpak index bb366735..86ccc12a 100755 --- a/host/rootfs/image/usr/bin/run-flatpak +++ b/host/rootfs/image/usr/bin/run-flatpak @@ -46,4 +46,6 @@ if { s6-instance-delete -- /run/service/vm-services $id }
if { umount ${dir}/mount } # mount namespace if { umount ${dir}/mount } # private bind mount +if { umount ${dir}/user } # user namespace +if { umount ${dir}/user } # private bind mount rm -r $dir /run/configs/${id}
Why is it necessary to unmount twice here?
Because we mount twice, just like the comments say. It is a bit counterintuitive though. Namespaces can only be mounted onto a mountpoint that itself has private propagation. This is why we create a private bind mount at the start of create-vm-dependencies before unshare bind mounts the namespaces. You can also see this in an example in unshare(1).
Perhaps it would be better and clearer to have /run/vm/by-id/${VM}/ns as a private mountpoint, with the nsfs files inside? That way, each of them only needs to be unmounted once, and then the ns directory also has to be unmounted once.
I think it would be easier to understand. -- Sincerely, Demi Marie Obenour (she/her/hers)
Demi Marie Obenour <demiobenour@gmail.com> writes:
On 12/11/25 07:41, Alyssa Ross wrote:
Demi Marie Obenour <demiobenour@gmail.com> writes:
On 12/10/25 07:47, Alyssa Ross wrote:
The document portal has to be root to mount its fuse filesystem. This needs to be a shared namespace because virtiofsd needs to be in the same mount namespace as the document portal so that it sees the fuse filesystem, so we create a per-VM persistent user namespace.
Signed-off-by: Alyssa Ross <hi@alyssa.is>
(snip)
diff --git a/host/rootfs/image/usr/bin/run-appimage b/host/rootfs/image/usr/bin/run-appimage index 47cab4c5..5e8e29fa 100755 --- a/host/rootfs/image/usr/bin/run-appimage +++ b/host/rootfs/image/usr/bin/run-appimage @@ -44,4 +44,6 @@ if { s6-instance-delete /run/service/vm-services $id }
if { umount ${dir}/mount } # mount namespace if { umount ${dir}/mount } # private bind mount +if { umount ${dir}/user } # user namespace +if { umount ${dir}/user } # private bind mount rm -r $dir /run/configs/${id} diff --git a/host/rootfs/image/usr/bin/run-flatpak b/host/rootfs/image/usr/bin/run-flatpak index bb366735..86ccc12a 100755 --- a/host/rootfs/image/usr/bin/run-flatpak +++ b/host/rootfs/image/usr/bin/run-flatpak @@ -46,4 +46,6 @@ if { s6-instance-delete -- /run/service/vm-services $id }
if { umount ${dir}/mount } # mount namespace if { umount ${dir}/mount } # private bind mount +if { umount ${dir}/user } # user namespace +if { umount ${dir}/user } # private bind mount rm -r $dir /run/configs/${id}
Why is it necessary to unmount twice here?
Because we mount twice, just like the comments say. It is a bit counterintuitive though. Namespaces can only be mounted onto a mountpoint that itself has private propagation. This is why we create a private bind mount at the start of create-vm-dependencies before unshare bind mounts the namespaces. You can also see this in an example in unshare(1).
Perhaps it would be better and clearer to have /run/vm/by-id/${VM}/ns as a private mountpoint, with the nsfs files inside? That way, each of them only needs to be unmounted once, and then the ns directory also has to be unmounted once.
I think it would be easier to understand.
Then you will like v2! https://spectrum-os.org/lists/archives/spectrum-devel/20251211162145.124509-...
This will enable running D-Bus as a user that does not have access to VM directories. Signed-off-by: Alyssa Ross <hi@alyssa.is> --- host/rootfs/image/usr/bin/create-vm-dependencies | 6 ++++-- .../services/org.freedesktop.portal.Documents.service | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/host/rootfs/image/usr/bin/create-vm-dependencies b/host/rootfs/image/usr/bin/create-vm-dependencies index 7ce19ed2..98f10489 100755 --- a/host/rootfs/image/usr/bin/create-vm-dependencies +++ b/host/rootfs/image/usr/bin/create-vm-dependencies @@ -8,7 +8,7 @@ if { mount --make-private --bind /run/vm/by-id/${1}/user /run/vm/by-id/${1}/user if { mkdir -p - /run/vm/by-id/${1}/doc-run/doc + /run/doc/${1}/doc /run/vm/by-id/${1}/fs/config /run/vm/by-id/${1}/fs/doc } @@ -27,7 +27,9 @@ if { # can be writable block-based bind mounted subdirectories. if { mount --rbind -o nofail /run/vm/by-id/${1}/config/fs /run/vm/by-id/${1}/fs/config } if { mount --rbind -o ro /run/vm/by-id/${1}/fs /run/vm/by-id/${1}/fs } - mount --rbind /run/vm/by-id/${1}/doc-run/doc /run/vm/by-id/${1}/fs/doc + + if { mount --make-shared --rbind /run/doc/${1} /run/doc/${1} } + mount --rbind /run/doc/${1}/doc /run/vm/by-id/${1}/fs/doc } if { s6-instance-create /run/service/vm-services $1 } diff --git a/host/rootfs/image/usr/share/dbus-1/services/org.freedesktop.portal.Documents.service b/host/rootfs/image/usr/share/dbus-1/services/org.freedesktop.portal.Documents.service index f4dd53e3..be24f080 100644 --- a/host/rootfs/image/usr/share/dbus-1/services/org.freedesktop.portal.Documents.service +++ b/host/rootfs/image/usr/share/dbus-1/services/org.freedesktop.portal.Documents.service @@ -3,4 +3,4 @@ [D-BUS Service] Name=org.freedesktop.portal.Documents -Exec=/bin/importas -Si VM export XDG_RUNTIME_DIR /run/vm/by-id/${VM}/doc-run xdg-document-portal +Exec=/bin/importas -Si VM export XDG_RUNTIME_DIR /run/doc/${VM} xdg-document-portal -- 2.51.0
On 12/10/25 07:47, Alyssa Ross wrote:
This will enable running D-Bus as a user that does not have access to VM directories.
Signed-off-by: Alyssa Ross <hi@alyssa.is> --- host/rootfs/image/usr/bin/create-vm-dependencies | 6 ++++-- .../services/org.freedesktop.portal.Documents.service | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-)
(snip)
@@ -27,7 +27,9 @@ if { # can be writable block-based bind mounted subdirectories. if { mount --rbind -o nofail /run/vm/by-id/${1}/config/fs /run/vm/by-id/${1}/fs/config } if { mount --rbind -o ro /run/vm/by-id/${1}/fs /run/vm/by-id/${1}/fs } - mount --rbind /run/vm/by-id/${1}/doc-run/doc /run/vm/by-id/${1}/fs/doc + + if { mount --make-shared --rbind /run/doc/${1} /run/doc/${1} } + mount --rbind /run/doc/${1}/doc /run/vm/by-id/${1}/fs/doc }
This could definitely use a lot more comments. For instance, why is --make-shared needed? What about --rbind? I trust that you tested this code and it works, but it isn't obvious *why* it works or why it must be written this way. It would be best to have a document explaining what all of the mount points and namespaces are, why they are as they are, and what mount propagation is involved. -- Sincerely, Demi Marie Obenour (she/her/hers)
Demi Marie Obenour <demiobenour@gmail.com> writes:
On 12/10/25 07:47, Alyssa Ross wrote:
This will enable running D-Bus as a user that does not have access to VM directories.
Signed-off-by: Alyssa Ross <hi@alyssa.is> --- host/rootfs/image/usr/bin/create-vm-dependencies | 6 ++++-- .../services/org.freedesktop.portal.Documents.service | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-)
(snip)
@@ -27,7 +27,9 @@ if { # can be writable block-based bind mounted subdirectories. if { mount --rbind -o nofail /run/vm/by-id/${1}/config/fs /run/vm/by-id/${1}/fs/config } if { mount --rbind -o ro /run/vm/by-id/${1}/fs /run/vm/by-id/${1}/fs } - mount --rbind /run/vm/by-id/${1}/doc-run/doc /run/vm/by-id/${1}/fs/doc + + if { mount --make-shared --rbind /run/doc/${1} /run/doc/${1} } + mount --rbind /run/doc/${1}/doc /run/vm/by-id/${1}/fs/doc }
This could definitely use a lot more comments. For instance, why is --make-shared needed? What about --rbind?
I trust that you tested this code and it works, but it isn't obvious *why* it works or why it must be written this way.
It would be best to have a document explaining what all of the mount points and namespaces are, why they are as they are, and what mount propagation is involved.
I think a separate document would quickly go out of date, but I'm happy to add some comments inline.
Alyssa Ross <hi@alyssa.is> writes:
Demi Marie Obenour <demiobenour@gmail.com> writes:
On 12/10/25 07:47, Alyssa Ross wrote:
This will enable running D-Bus as a user that does not have access to VM directories.
Signed-off-by: Alyssa Ross <hi@alyssa.is> --- host/rootfs/image/usr/bin/create-vm-dependencies | 6 ++++-- .../services/org.freedesktop.portal.Documents.service | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-)
(snip)
@@ -27,7 +27,9 @@ if { # can be writable block-based bind mounted subdirectories. if { mount --rbind -o nofail /run/vm/by-id/${1}/config/fs /run/vm/by-id/${1}/fs/config } if { mount --rbind -o ro /run/vm/by-id/${1}/fs /run/vm/by-id/${1}/fs } - mount --rbind /run/vm/by-id/${1}/doc-run/doc /run/vm/by-id/${1}/fs/doc + + if { mount --make-shared --rbind /run/doc/${1} /run/doc/${1} } + mount --rbind /run/doc/${1}/doc /run/vm/by-id/${1}/fs/doc }
This could definitely use a lot more comments. For instance, why is --make-shared needed? What about --rbind?
I trust that you tested this code and it works, but it isn't obvious *why* it works or why it must be written this way.
It would be best to have a document explaining what all of the mount points and namespaces are, why they are as they are, and what mount propagation is involved.
I think a separate document would quickly go out of date, but I'm happy to add some comments inline.
--rbind is perhaps worth discussing. I consider it best practice to always use --rbind over --bind, because generally the idea with a bind mount is to copy a whole hierarchy from one place to another. With --bind you have to know the internal structure of that hierarchy and be sure you only want the top-level mount; with --rbind you just think in terms of the hierarchy. There are also some situations where it's mandatory to use --rbind: where a --bind would reveal hierarchies in the mountpoint that have been hidden by extra bind mounts being placed over the top. (I won't put this in a comment here because we use --rbind all over the place, but it's something that would make sense to put into developer guidelines once we have a documentation structure that accomodates such a thing.)
This will enable running virtiofsd as a user that does not have access to VM directories. Signed-off-by: Alyssa Ross <hi@alyssa.is> --- .../template/data/service/vhost-user-fs/run | 2 +- host/rootfs/image/usr/bin/create-vm-dependencies | 12 +++++------- host/rootfs/image/usr/bin/run-appimage | 2 +- host/rootfs/image/usr/bin/run-flatpak | 2 +- host/rootfs/image/usr/bin/spectrum-update | 14 +++++++------- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run index 79830a00..116570c3 100755 --- a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run +++ b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run @@ -15,4 +15,4 @@ importas -i VM VM nsenter --mount=/run/vm/by-id/${VM}/mount unshare -U --map-user 1000 --map-group 1000 --uts --ipc --cgroup -virtiofsd --fd 3 --shared-dir /run/vm/by-id/${VM}/fs +virtiofsd --fd 3 --shared-dir /run/fs/${VM} diff --git a/host/rootfs/image/usr/bin/create-vm-dependencies b/host/rootfs/image/usr/bin/create-vm-dependencies index 98f10489..344e7778 100755 --- a/host/rootfs/image/usr/bin/create-vm-dependencies +++ b/host/rootfs/image/usr/bin/create-vm-dependencies @@ -9,8 +9,8 @@ if { mount --make-private --bind /run/vm/by-id/${1}/user /run/vm/by-id/${1}/user if { mkdir -p /run/doc/${1}/doc - /run/vm/by-id/${1}/fs/config - /run/vm/by-id/${1}/fs/doc + /run/fs/${1}/config + /run/fs/${1}/doc } if { @@ -20,16 +20,14 @@ if { --mount=/run/vm/by-id/${1}/mount --user=/run/vm/by-id/${1}/user - if { mount --make-shared --rbind /run/vm/by-id/${1} /run/vm/by-id/${1} } - # The VM should not be able to write directly into a tmpfs, and the host # should be able to assume there are no untrusted symlinks there, but there # can be writable block-based bind mounted subdirectories. - if { mount --rbind -o nofail /run/vm/by-id/${1}/config/fs /run/vm/by-id/${1}/fs/config } - if { mount --rbind -o ro /run/vm/by-id/${1}/fs /run/vm/by-id/${1}/fs } + if { mount --make-shared --rbind -o nofail /run/vm/by-id/${1}/config/fs /run/fs/${1}/config } + if { mount --rbind -o ro /run/fs/${1} /run/fs/${1} } if { mount --make-shared --rbind /run/doc/${1} /run/doc/${1} } - mount --rbind /run/doc/${1}/doc /run/vm/by-id/${1}/fs/doc + mount --rbind /run/doc/${1}/doc /run/fs/${1}/doc } if { s6-instance-create /run/service/vm-services $1 } diff --git a/host/rootfs/image/usr/bin/run-appimage b/host/rootfs/image/usr/bin/run-appimage index 5e8e29fa..f0fe8311 100755 --- a/host/rootfs/image/usr/bin/run-appimage +++ b/host/rootfs/image/usr/bin/run-appimage @@ -20,7 +20,7 @@ if { create-vm-dependencies $id } if { nsenter --mount=${dir}/mount - cd ${dir}/fs/config + cd /run/fs/${id}/config if { redirfd -w 1 type echo appimage } if { touch run } mount --bind $1 run diff --git a/host/rootfs/image/usr/bin/run-flatpak b/host/rootfs/image/usr/bin/run-flatpak index 86ccc12a..f9179819 100755 --- a/host/rootfs/image/usr/bin/run-flatpak +++ b/host/rootfs/image/usr/bin/run-flatpak @@ -23,7 +23,7 @@ if { if { nsenter --mount=${dir}/mount - cd ${dir}/fs/config + cd /run/fs/${id}/config if { redirfd -w 1 type echo flatpak } mount-flatpak $@ } diff --git a/host/rootfs/image/usr/bin/spectrum-update b/host/rootfs/image/usr/bin/spectrum-update index b1517a6c..10a9f197 100755 --- a/host/rootfs/image/usr/bin/spectrum-update +++ b/host/rootfs/image/usr/bin/spectrum-update @@ -43,11 +43,11 @@ foreground { # mounts instead of rm -rf. Once this code is in a separate mount # namespace, the copies should be replaced by bind mounts. if { - if { rm -rf -- /run/vm/by-id/${update_vm_id}/fs/etc } + if { rm -rf -- /run/fs/${update_vm_id}/etc } umask 022 - if { mkdir -p -- /run/vm/by-id/${update_vm_id}/fs/updates /run/vm/by-id/${update_vm_id}/fs/etc/systemd } - if { cp -R -- /etc/vm-sysupdate.d /etc/update-url /run/vm/by-id/${update_vm_id}/fs/etc } - cp -- /etc/systemd/import-pubring.gpg /run/vm/by-id/${update_vm_id}/fs/etc/systemd + if { mkdir -p -- /run/fs/${update_vm_id}/updates /run/fs/${update_vm_id}/etc/systemd } + if { cp -R -- /etc/vm-sysupdate.d /etc/update-url /run/fs/${update_vm_id}/etc } + cp -- /etc/systemd/import-pubring.gpg /run/fs/${update_vm_id}/etc/systemd } nsenter --mount=/run/vm/by-id/${update_vm_id}/mount @@ -55,10 +55,10 @@ foreground { # If the directory is already mounted, unmount it. This prevents a # confusing error from mount. - foreground { redirfd -w 2 /dev/null umount -- /run/vm/by-id/${update_vm_id}/fs/updates } + foreground { redirfd -w 2 /dev/null umount -- /run/fs/${update_vm_id}/updates } # Share the update directory with the VM. - if { mount --bind -- shared /run/vm/by-id/${update_vm_id}/fs/updates } + if { mount --bind -- shared /run/fs/${update_vm_id}/updates } # Start the update VM. if { vm-start $update_vm_id } @@ -69,7 +69,7 @@ foreground { if { s6-svwait -D /run/service/vmm/instance/${update_vm_id} } # Remove the bind mount. - if { umount -- /run/vm/by-id/${update_vm_id}/fs/updates } + if { umount -- /run/fs/${update_vm_id}/updates } # Ensure that the VM cannot change the directory # while systemd-sysupdate is using it. -- 2.51.0
We'd like these to be non-root, but xdg-document-portal in particular still needs to be root within its namespace so it can mount a fuse filesystem. We therefore map the fs user in the host namespace to root in the new namespace, and pass through every non-root user so non-root users (e.g. for xdg-desktop-portal-spectrum) are still usable within the namespace. Signed-off-by: Alyssa Ross <hi@alyssa.is> --- .../image/etc/s6-linux-init/run-image/etc/group | 1 + .../image/etc/s6-linux-init/run-image/etc/passwd | 1 + .../vm-services/template/data/service/dbus/run | 6 +++++- .../template/data/service/vhost-user-fs/run | 7 ++++++- .../service/xdg-desktop-portal-spectrum-host/run | 6 ++++++ host/rootfs/image/usr/bin/create-vm-dependencies | 13 +++++++++---- host/rootfs/image/usr/bin/run-flatpak | 8 ++++++-- 7 files changed, 34 insertions(+), 8 deletions(-) diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/etc/group b/host/rootfs/image/etc/s6-linux-init/run-image/etc/group index 019f5525..6e894d93 100644 --- a/host/rootfs/image/etc/s6-linux-init/run-image/etc/group +++ b/host/rootfs/image/etc/s6-linux-init/run-image/etc/group @@ -14,3 +14,4 @@ cdrom:x:12: tape:x:13: kvm:x:14: wayland:x:15:wayland +fs:x:1000: diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/etc/passwd b/host/rootfs/image/etc/s6-linux-init/run-image/etc/passwd index 50def56d..dc104ec1 100644 --- a/host/rootfs/image/etc/s6-linux-init/run-image/etc/passwd +++ b/host/rootfs/image/etc/s6-linux-init/run-image/etc/passwd @@ -1,2 +1,3 @@ root:x:0:0:System administrator:/:/bin/sh wayland:x:15:15:Wayland compositor:/:/bin/nologin +fs:x:1000:1000:Spectrum files:/:/bin/nologin 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 20f1daff..7330ab4c 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 @@ -14,8 +14,12 @@ s6-ipcserver-socketbinder -B /run/portal-bus/${VM} fdmove -c 3 0 redirfd -r 0 /dev/null +s6-envuidgid fs +s6-applyuidgid -Uzu 0 getcwd -E dir -nsenter --mount=/run/vm/by-id/${VM}/mount +nsenter --preserve-credentials -S0 + --mount=/run/vm/by-id/${VM}/mount + --user=/run/vm/by-id/${VM}/user unshare --cgroup --ipc --net --uts diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run index 116570c3..525940d1 100755 --- a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run +++ b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run @@ -10,9 +10,14 @@ redirfd -r 0 /dev/null export TMPDIR /run +s6-envuidgid fs +s6-applyuidgid -Uzu 0 importas -i VM VM +nsenter --preserve-credentials -S0 + --mount=/run/vm/by-id/${VM}/mount + --user=/run/vm/by-id/${VM}/user -nsenter --mount=/run/vm/by-id/${VM}/mount +# Show the guest files owned by uid/gid 1000. unshare -U --map-user 1000 --map-group 1000 --uts --ipc --cgroup virtiofsd --fd 3 --shared-dir /run/fs/${VM} 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 b83d23dd..cb2195d1 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,6 +13,12 @@ s6-ipcserver-socketbinder -a 0700 /run/vsock/${VM}/vsock_219 if { fdmove 1 3 echo } fdclose 3 +s6-envuidgid fs +s6-applyuidgid -Uzu 0 +nsenter --preserve-credentials -S0 + --mount=/run/vm/by-id/${VM}/mount + --user=/run/vm/by-id/${VM}/user + s6-setuidgid xdp-spectrum-${VM} xdg-desktop-portal-spectrum-host diff --git a/host/rootfs/image/usr/bin/create-vm-dependencies b/host/rootfs/image/usr/bin/create-vm-dependencies index 344e7778..6f9d0a60 100755 --- a/host/rootfs/image/usr/bin/create-vm-dependencies +++ b/host/rootfs/image/usr/bin/create-vm-dependencies @@ -14,16 +14,21 @@ if { } if { - unshare --propagation=slave - --map-users all - --map-groups all + redirfd -r 3 /run/vm/by-id/${1}/config + + s6-envuidgid fs + s6-applyuidgid -Uzu 0 + + unshare -S0 --propagation=slave + --map-users 0:1000:1 --map-users 1:1:999 --map-users 1001:1001:4294966294 + --map-groups 0:1000:1 --map-groups 1:1:999 --map-groups 1001:1001:4294966294 --mount=/run/vm/by-id/${1}/mount --user=/run/vm/by-id/${1}/user # The VM should not be able to write directly into a tmpfs, and the host # should be able to assume there are no untrusted symlinks there, but there # can be writable block-based bind mounted subdirectories. - if { mount --make-shared --rbind -o nofail /run/vm/by-id/${1}/config/fs /run/fs/${1}/config } + if { mount --make-shared --rbind -o nofail /proc/self/fd/3/fs /run/fs/${1}/config } if { mount --rbind -o ro /run/fs/${1} /run/fs/${1} } if { mount --make-shared --rbind /run/doc/${1} /run/doc/${1} } diff --git a/host/rootfs/image/usr/bin/run-flatpak b/host/rootfs/image/usr/bin/run-flatpak index f9179819..695df21f 100755 --- a/host/rootfs/image/usr/bin/run-flatpak +++ b/host/rootfs/image/usr/bin/run-flatpak @@ -10,7 +10,7 @@ if { useradd -P /run -Urd / -s /bin/nologin xdp-spectrum-${id} } if { elgetpositionals - if { mkdir -p /run/configs/${id}/fs } + if { install -do fs /run/configs/${id}/fs } if { ln -s /usr/lib/spectrum/img/appvm/blk /usr/lib/spectrum/img/appvm/vmlinux @@ -22,7 +22,11 @@ if { if { create-vm-dependencies $id } if { - nsenter --mount=${dir}/mount + s6-envuidgid fs + s6-applyuidgid -Uzu 0 + nsenter --preserve-credentials -S0 + --mount=/run/vm/by-id/${id}/mount + --user=/run/vm/by-id/${id}/user cd /run/fs/${id}/config if { redirfd -w 1 type echo flatpak } mount-flatpak $@ -- 2.51.0
On 12/10/25 07:47, Alyssa Ross wrote:
We'd like these to be non-root, but xdg-document-portal in particular still needs to be root within its namespace so it can mount a fuse filesystem. We therefore map the fs user in the host namespace to root in the new namespace, and pass through every non-root user so non-root users (e.g. for xdg-desktop-portal-spectrum) are still usable within the namespace.
Signed-off-by: Alyssa Ross <hi@alyssa.is> --- .../image/etc/s6-linux-init/run-image/etc/group | 1 + .../image/etc/s6-linux-init/run-image/etc/passwd | 1 + .../vm-services/template/data/service/dbus/run | 6 +++++- .../template/data/service/vhost-user-fs/run | 7 ++++++- .../service/xdg-desktop-portal-spectrum-host/run | 6 ++++++ host/rootfs/image/usr/bin/create-vm-dependencies | 13 +++++++++---- host/rootfs/image/usr/bin/run-flatpak | 8 ++++++-- 7 files changed, 34 insertions(+), 8 deletions(-)
diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/etc/group b/host/rootfs/image/etc/s6-linux-init/run-image/etc/group index 019f5525..6e894d93 100644 --- a/host/rootfs/image/etc/s6-linux-init/run-image/etc/group +++ b/host/rootfs/image/etc/s6-linux-init/run-image/etc/group @@ -14,3 +14,4 @@ cdrom:x:12: tape:x:13: kvm:x:14: wayland:x:15:wayland +fs:x:1000:
Would it be better to run each VM's daemons as dedicated users?
diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/etc/passwd b/host/rootfs/image/etc/s6-linux-init/run-image/etc/passwd index 50def56d..dc104ec1 100644 --- a/host/rootfs/image/etc/s6-linux-init/run-image/etc/passwd +++ b/host/rootfs/image/etc/s6-linux-init/run-image/etc/passwd @@ -1,2 +1,3 @@ root:x:0:0:System administrator:/:/bin/sh wayland:x:15:15:Wayland compositor:/:/bin/nologin +fs:x:1000:1000:Spectrum files:/:/bin/nologin 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 20f1daff..7330ab4c 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 @@ -14,8 +14,12 @@ s6-ipcserver-socketbinder -B /run/portal-bus/${VM} fdmove -c 3 0 redirfd -r 0 /dev/null
+s6-envuidgid fs +s6-applyuidgid -Uzu 0 getcwd -E dir -nsenter --mount=/run/vm/by-id/${VM}/mount +nsenter --preserve-credentials -S0 + --mount=/run/vm/by-id/${VM}/mount + --user=/run/vm/by-id/${VM}/user
unshare --cgroup --ipc --net --uts
diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run index 116570c3..525940d1 100755 --- a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run +++ b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run @@ -10,9 +10,14 @@ redirfd -r 0 /dev/null
export TMPDIR /run
+s6-envuidgid fs +s6-applyuidgid -Uzu 0 importas -i VM VM +nsenter --preserve-credentials -S0 + --mount=/run/vm/by-id/${VM}/mount + --user=/run/vm/by-id/${VM}/user
-nsenter --mount=/run/vm/by-id/${VM}/mount +# Show the guest files owned by uid/gid 1000. unshare -U --map-user 1000 --map-group 1000 --uts --ipc --cgroup
virtiofsd --fd 3 --shared-dir /run/fs/${VM} 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 b83d23dd..cb2195d1 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,6 +13,12 @@ s6-ipcserver-socketbinder -a 0700 /run/vsock/${VM}/vsock_219 if { fdmove 1 3 echo } fdclose 3
+s6-envuidgid fs +s6-applyuidgid -Uzu 0 +nsenter --preserve-credentials -S0 + --mount=/run/vm/by-id/${VM}/mount + --user=/run/vm/by-id/${VM}/user + s6-setuidgid xdp-spectrum-${VM}
xdg-desktop-portal-spectrum-host diff --git a/host/rootfs/image/usr/bin/create-vm-dependencies b/host/rootfs/image/usr/bin/create-vm-dependencies index 344e7778..6f9d0a60 100755 --- a/host/rootfs/image/usr/bin/create-vm-dependencies +++ b/host/rootfs/image/usr/bin/create-vm-dependencies @@ -14,16 +14,21 @@ if { }
if { - unshare --propagation=slave - --map-users all - --map-groups all + redirfd -r 3 /run/vm/by-id/${1}/config + + s6-envuidgid fs + s6-applyuidgid -Uzu 0 + + unshare -S0 --propagation=slave + --map-users 0:1000:1 --map-users 1:1:999 --map-users 1001:1001:4294966294 + --map-groups 0:1000:1 --map-groups 1:1:999 --map-groups 1001:1001:4294966294 --mount=/run/vm/by-id/${1}/mount --user=/run/vm/by-id/${1}/user
# The VM should not be able to write directly into a tmpfs, and the host # should be able to assume there are no untrusted symlinks there, but there # can be writable block-based bind mounted subdirectories. - if { mount --make-shared --rbind -o nofail /run/vm/by-id/${1}/config/fs /run/fs/${1}/config } + if { mount --make-shared --rbind -o nofail /proc/self/fd/3/fs /run/fs/${1}/config }
Why is this -o nofail? Also, file descriptor 3 should be closed afterwards.
if { mount --rbind -o ro /run/fs/${1} /run/fs/${1} }
if { mount --make-shared --rbind /run/doc/${1} /run/doc/${1} } diff --git a/host/rootfs/image/usr/bin/run-flatpak b/host/rootfs/image/usr/bin/run-flatpak index f9179819..695df21f 100755 --- a/host/rootfs/image/usr/bin/run-flatpak +++ b/host/rootfs/image/usr/bin/run-flatpak @@ -10,7 +10,7 @@ if { useradd -P /run -Urd / -s /bin/nologin xdp-spectrum-${id} } if { elgetpositionals
- if { mkdir -p /run/configs/${id}/fs } + if { install -do fs /run/configs/${id}/fs }
if { ln -s /usr/lib/spectrum/img/appvm/blk /usr/lib/spectrum/img/appvm/vmlinux @@ -22,7 +22,11 @@ if { if { create-vm-dependencies $id }
if { - nsenter --mount=${dir}/mount + s6-envuidgid fs + s6-applyuidgid -Uzu 0 + nsenter --preserve-credentials -S0 + --mount=/run/vm/by-id/${id}/mount + --user=/run/vm/by-id/${id}/user cd /run/fs/${id}/config if { redirfd -w 1 type echo flatpak } mount-flatpak $@
-- Sincerely, Demi Marie Obenour (she/her/hers)
Demi Marie Obenour <demiobenour@gmail.com> writes:
On 12/10/25 07:47, Alyssa Ross wrote:
We'd like these to be non-root, but xdg-document-portal in particular still needs to be root within its namespace so it can mount a fuse filesystem. We therefore map the fs user in the host namespace to root in the new namespace, and pass through every non-root user so non-root users (e.g. for xdg-desktop-portal-spectrum) are still usable within the namespace.
Signed-off-by: Alyssa Ross <hi@alyssa.is> --- .../image/etc/s6-linux-init/run-image/etc/group | 1 + .../image/etc/s6-linux-init/run-image/etc/passwd | 1 + .../vm-services/template/data/service/dbus/run | 6 +++++- .../template/data/service/vhost-user-fs/run | 7 ++++++- .../service/xdg-desktop-portal-spectrum-host/run | 6 ++++++ host/rootfs/image/usr/bin/create-vm-dependencies | 13 +++++++++---- host/rootfs/image/usr/bin/run-flatpak | 8 ++++++-- 7 files changed, 34 insertions(+), 8 deletions(-)
diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/etc/group b/host/rootfs/image/etc/s6-linux-init/run-image/etc/group index 019f5525..6e894d93 100644 --- a/host/rootfs/image/etc/s6-linux-init/run-image/etc/group +++ b/host/rootfs/image/etc/s6-linux-init/run-image/etc/group @@ -14,3 +14,4 @@ cdrom:x:12: tape:x:13: kvm:x:14: wayland:x:15:wayland +fs:x:1000:
Would it be better to run each VM's daemons as dedicated users?
Not really, because they all need to have access to the same files on the filesystem anyway. The separate namespaces stop them from doing things like ptracing each other, but at the end of the day they need to all be able to access the same set of user files.
diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/etc/passwd b/host/rootfs/image/etc/s6-linux-init/run-image/etc/passwd index 50def56d..dc104ec1 100644 --- a/host/rootfs/image/etc/s6-linux-init/run-image/etc/passwd +++ b/host/rootfs/image/etc/s6-linux-init/run-image/etc/passwd @@ -1,2 +1,3 @@ root:x:0:0:System administrator:/:/bin/sh wayland:x:15:15:Wayland compositor:/:/bin/nologin +fs:x:1000:1000:Spectrum files:/:/bin/nologin 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 20f1daff..7330ab4c 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 @@ -14,8 +14,12 @@ s6-ipcserver-socketbinder -B /run/portal-bus/${VM} fdmove -c 3 0 redirfd -r 0 /dev/null
+s6-envuidgid fs +s6-applyuidgid -Uzu 0 getcwd -E dir -nsenter --mount=/run/vm/by-id/${VM}/mount +nsenter --preserve-credentials -S0 + --mount=/run/vm/by-id/${VM}/mount + --user=/run/vm/by-id/${VM}/user
unshare --cgroup --ipc --net --uts
diff --git a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run index 116570c3..525940d1 100755 --- a/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run +++ b/host/rootfs/image/etc/s6-linux-init/run-image/service/vm-services/template/data/service/vhost-user-fs/run @@ -10,9 +10,14 @@ redirfd -r 0 /dev/null
export TMPDIR /run
+s6-envuidgid fs +s6-applyuidgid -Uzu 0 importas -i VM VM +nsenter --preserve-credentials -S0 + --mount=/run/vm/by-id/${VM}/mount + --user=/run/vm/by-id/${VM}/user
-nsenter --mount=/run/vm/by-id/${VM}/mount +# Show the guest files owned by uid/gid 1000. unshare -U --map-user 1000 --map-group 1000 --uts --ipc --cgroup
virtiofsd --fd 3 --shared-dir /run/fs/${VM} 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 b83d23dd..cb2195d1 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,6 +13,12 @@ s6-ipcserver-socketbinder -a 0700 /run/vsock/${VM}/vsock_219 if { fdmove 1 3 echo } fdclose 3
+s6-envuidgid fs +s6-applyuidgid -Uzu 0 +nsenter --preserve-credentials -S0 + --mount=/run/vm/by-id/${VM}/mount + --user=/run/vm/by-id/${VM}/user + s6-setuidgid xdp-spectrum-${VM}
xdg-desktop-portal-spectrum-host diff --git a/host/rootfs/image/usr/bin/create-vm-dependencies b/host/rootfs/image/usr/bin/create-vm-dependencies index 344e7778..6f9d0a60 100755 --- a/host/rootfs/image/usr/bin/create-vm-dependencies +++ b/host/rootfs/image/usr/bin/create-vm-dependencies @@ -14,16 +14,21 @@ if { }
if { - unshare --propagation=slave - --map-users all - --map-groups all + redirfd -r 3 /run/vm/by-id/${1}/config + + s6-envuidgid fs + s6-applyuidgid -Uzu 0 + + unshare -S0 --propagation=slave + --map-users 0:1000:1 --map-users 1:1:999 --map-users 1001:1001:4294966294 + --map-groups 0:1000:1 --map-groups 1:1:999 --map-groups 1001:1001:4294966294 --mount=/run/vm/by-id/${1}/mount --user=/run/vm/by-id/${1}/user
# The VM should not be able to write directly into a tmpfs, and the host # should be able to assume there are no untrusted symlinks there, but there # can be writable block-based bind mounted subdirectories. - if { mount --make-shared --rbind -o nofail /run/vm/by-id/${1}/config/fs /run/fs/${1}/config } + if { mount --make-shared --rbind -o nofail /proc/self/fd/3/fs /run/fs/${1}/config }
Why is this -o nofail? Also, file descriptor 3 should be closed afterwards.
Same reason as always. Not all VMs have an fs directory in config, notably netvm. Descriptor 3 will be closed at the end of this block in a few lines anyway. It does no harm to keep it open until then.
participants (2)
-
Alyssa Ross -
Demi Marie Obenour