Public bug reported:

systemd.exec(5) for this version says of ProtectKernelTunables=: "If
true, kernel variables accessible through /proc/sys/, /sys/,
/proc/sysrq-trigger, /proc/latency_stats, /proc/acpi, /proc/timer_stats,
/proc/fs and /proc/irq will be made read-only to all processes of the
unit." On Ubuntu 24.04.5 (systemd 255.4-1ubuntu8.18, kernel
6.8.0-147-generic, amd64), /sys stays read-write. It also cancels an
explicit ReadOnlyPaths=/sys or TemporaryFileSystem=/sys:ro. /proc/sys is
made read-only as documented.

Reproduction, as root, no unit file needed (awk '$5=="/sys"' picks the
/sys mount itself):

# 1. ReadOnlyPaths=/sys alone: read-only, as expected
systemd-run --wait --pipe -p ReadOnlyPaths=/sys awk '$5=="/sys"' 
/proc/self/mountinfo
426 409 0:23 / /sys ro,nosuid,nodev,noexec,relatime shared:417 master:7 - sysfs 
sysfs rw
# 2. Adding ProtectKernelTunables=yes: read-write
systemd-run --wait --pipe -p ReadOnlyPaths=/sys -p ProtectKernelTunables=yes 
awk '$5=="/sys"' /proc/self/mountinfo
426 409 0:23 / /sys rw,nosuid,nodev,noexec,relatime shared:417 master:7 - sysfs 
sysfs rw
# 3. TemporaryFileSystem=/sys:ro is not applied either
systemd-run --wait --pipe -p ProtectKernelTunables=yes -p 
TemporaryFileSystem=/sys:ro sh -c "awk '\$5==\"/sys\"' /proc/self/mountinfo; ls 
/sys | wc -l"
426 409 0:23 / /sys rw,nosuid,nodev,noexec,relatime shared:417 master:7 - sysfs 
sysfs rw
11
# 4. Workaround: BindReadOnlyPaths=/sys stacks a read-only /sys, sub-mounts 
read-only
systemd-run --wait --pipe -p ProtectKernelTunables=yes -p 
BindReadOnlyPaths=/sys sh -c 'grep -E " /sys(/| )" /proc/self/mountinfo | cut 
-d" " -f1,2,5,6'
426 409 /sys rw,nosuid,nodev,noexec,relatime
463 426 /sys/firmware/efi/efivars rw,nosuid,nodev,noexec,relatime
...
515 426 /sys ro,nosuid,nodev,noexec,relatime
516 515 /sys/firmware/efi/efivars ro,nosuid,nodev,noexec,relatime
...
(Runs 2 and 3 were measured with grep " /sys ", which also printed the 
/proc/sys line, shown read-only. The awk form above prints only /sys.)

Corroboration from a real service with ProtectSystem=strict,
ProtectKernelTunables=yes, ProtectControlGroups=yes, PrivateDevices=yes
and ReadOnlyPaths=/run /sys: its /proc/<MainPID>/mountinfo showed /run
read-only and /sys read-write, along with /sys/firmware/efi/efivars,
/sys/kernel/security, /sys/fs/pstore, /sys/kernel/config and
/sys/fs/fuse/connections.

Likely cause, from upstream source (v255 src/core/namespace.c; main is
the same):

ProtectKernelTunables= enables the API VFS mounts, adding { "/sys", 
MOUNT_BIND_SYSFS }. That mode ranks ahead of MOUNT_READ_ONLY in the 
priority-ordered enum, so deduplication keeps it and folds in the read-only 
flag from ProtectKernelTunables= and ReadOnlyPaths=.
mount_bind_sysfs() is a no-op when /sys is already a mount point, so the entry 
ends up MOUNT_SKIPPED.
Since commit 63862de4b7 ("core: do not post-process skipped mounts", PR 29728), 
make_read_only() returns early for skipped entries, so /sys is never remounted 
read-only.
TemporaryFileSystem= ranks after MOUNT_BIND_SYSFS and is dropped as a 
duplicate. BindReadOnlyPaths= ranks ahead of it, which is why the workaround 
holds.
If that is right, it is a v255 regression and still present upstream. We have 
not tested v254 or a current upstream release. Please forward upstream if 
confirmed.

Expected: with ProtectKernelTunables=yes, /sys is mounted read-only,
apart from /sys/fs/cgroup, which ProtectControlGroups= governs. An
explicit ReadOnlyPaths=/sys is never weakened by another sandboxing
option.

Impact, inferred from the code, not exercised: a service running as uid
0 with an empty capability bounding set can still write sysfs attributes
whose store handlers check only file permissions. It can also write
efivarfs variables that the kernel does not mark immutable: in Linux 6.8
they are created mode 0644 owned by root, the write path has no
capability check, and only variables outside the kernel's known list get
S_IMMUTABLE, so Boot*, BootOrder, BootNext and similar are writable.
That is where the documentation says /sys is read-only.

** Affects: systemd (Ubuntu)
     Importance: Undecided
         Status: New


** Tags: noble

** Tags added: noble

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2173130

Title:
  ProtectKernelTunables=yes leaves /sys read-write and overrides
  ReadOnlyPaths= and TemporaryFileSystem= for /sys (255.4-1ubuntu8.18;
  upstream v255+)

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2173130/+subscriptions


-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to