If the target mount point is an automount, checking it for writeability
without triggering it first is iffy and yields different results based
on kernel version:
~# systemd-run --wait --pipe -p ProtectSystem=yes bash -xec 'uname -r; mount -l | grep boot; test ! -w /boot'
Running as unit: run-u36.service; invocation ID: f948ff4f3c8e4bcfba364ead94bd0ad9
+ uname -r
4.18.0-529.el8.x86_64
+ mount -l
+ grep boot
systemd-1 on /boot type autofs (rw,relatime,fd=43,pgrp=1,timeout=120,minproto=5,maxproto=5,direct,pipe_ino=356096)
+ test '!' -w /boot
Finished with result: exit-code
Main processes terminated with: code=exited/status=1
~# systemd-run --wait --pipe -p ProtectSystem=yes bash -xec 'uname -r; mount -l | grep boot; test ! -w /boot'
Running as unit: run-u274.service; invocation ID: ccc53ed63c3249348cf714f97a3a7026
+ uname -r
6.6.7-arch1-1
+ mount -l
+ grep boot
systemd-1 on /boot type autofs (rw,relatime,fd=95,pgrp=1,timeout=120,minproto=5,maxproto=5,direct,pipe_ino=730583)
+ test '!' -w /boot
Finished with result: success
Main processes terminated with: code=exited/status=0
One solution would be to use /boot/ instead of just /boot, which triggers
the automount during the check, but in that case the mount would happen
_after_ we apply the ProtectSystem= stuff, so the mount point would
be unexpectedly writable:
~# systemd-run --wait --pipe -p ProtectSystem=yes bash -xec 'uname -r; mount -l | grep boot; test ! -w /boot/ || mount -l | grep boot'
Running as unit: run-u282.service; invocation ID: 2154f6b4cbd34ddeb3e246cb7c991918
+ uname -r
6.6.7-arch1-1
+ mount -l
+ grep boot
systemd-1 on /boot type autofs (rw,relatime,fd=95,pgrp=1,timeout=120,minproto=5,maxproto=5,direct,pipe_ino=730583)
+ test '!' -w /boot/
+ mount -l
+ grep boot
systemd-1 on /boot type autofs (rw,relatime,fd=95,pgrp=1,timeout=120,minproto=5,maxproto=5,direct,pipe_ino=730583)
/dev/vda2 on /boot type vfat (rw,nosuid,nodev,noexec,relatime,nosymfollow,fmask=0077,dmask=0077,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro)
Let's just trigger the (possible) automounts explicitly before we do any
checks to avoid all this stuff.
Also, when at it, check that ProtectSystem=yes|full correctly protects
the ESP mount as well.
Follow-up for 97bbb9cfbd.
The errors are valid, since the file system is indeed not writable, but
we don't care about the missing coverage data in this case.
Follow-up to 4a43c2b3a1.
When a late error occurs in sd-executor, the cleanup-on-close of the
context structs happen, but at that time all FDs might have already
been closed via close_all_fds(), so a double-close happens. This
can be seen when DynamicUser is enabled, with a non-existing
WorkingDirectory.
Invalidate the FDs in the context structs if close_all_fds succeeds.
When a mount is gracefully skipped (e.g.: BindReadOnlyPaths=-/nonexistent)
we still post-process it, like making it read-only. Except if nothing
has been mounted, the mount point will be made read-only for no reason.
Track when mounts are skipped and avoid post-processing.
One day we'll switch all of this to the new mount api and do these
operations atomically or not at all.
Fixes https://github.com/systemd/systemd/issues/29725
With coverage builds we disable Protect{Home,System}= via a service.d
dropin in /etc, which has, unfortunately, higher priority than our
transient systemd-run stuff. Let's just skip the affected tests in that
case instead of making the test setup even more complicated.