This new tool looks for a three xattr on the root inode of a file system
that encode mount constraints of the file system. The tool is supposed
to be hooke into the mount logic and is supposed to protect against
misappropriating trusted file systems in unintended ways.
Consider the following scenario: we boot up on first boot and create a
tpm-locked pair of /var/ and /srv/ partitions via systemd-repart. An
attacker then offline modifies the partition table, exchanging the
metadata of the /var/ and /srv/ partition. So far we'd happily accept
that, honour the modified metadata and boot up. This could be used to
revert changes to /var/ or similar. And all that even though both
partitions are encrypted and locked to TPM!
With this new mechanism we can encode in the protected contents of the
file systems the ways it can be used: the partition type uuid, the
partition label and the intended mount point can be stored in xattrs,
and we can check them automatically on mount, and take action on
mismatch. (action would typically be immediate reboot).
PCR extensions are supposed to be useful for "destroying" the ability to
access TPM bound secrets. Hence, if for some reason we fail to extend a
PCR, it's safer to just reboot, instead of going on without the
extension, leaving secrets potentially accessible which should not be
accessible.
Note that the services exit gracefully if no TPM is found, hence this
should not be triggered on TPM-less systems. However, this enforces that
if there is a TPM that is accessible to Linux and that works properly,
the PCR measurement must complete too.
Inspired by this thread:
https://lists.freedesktop.org/archives/systemd-devel/2025-March/051244.html
Let's always prefer quotactl_fd() when it's available and use quotactl()
only as as a fallback on old kernels.
This way we can operate on the fds we typically already have open, or if
needed we can open a new one, and use for multiple fs operation.
In the long run we should really focus on operating exclusively by fd
instead of by path, by device nor or otherwise. This gets us a step
closer to that.
Instead of listing dependencies manually for the default tools tree,
let's reuse the prepare scripts from the build image. To make this work,
the sync script has to be configured for the tools tree as well so that
it's invoked both when building the tools tree and for the regular
image,
otherwise, when doing the first build in a fresh checkout, the sync
script
won't have executed yet as sync scripts for the regular images are
executed
after building the default tools tree.
With meson 1.7.0, meson won't rebuild the world anymore when running
meson test so since meson 1.7.0 is in tumbleweed, debian testing, fedora
rawhide and Arch Linux, drop --no-rebuild from the docs since all the default
tools trees built by mkosi in the systemd repo will have meson 1.7.0 or newer
installed.
We keep --no-rebuild in CI because in CI we run with the same tools tree
distribution as the target distribution we're building and in those it's not
guaranteed for meson 1.7.0 to be available yet.
The advantage of dropping --no-rebuild is that meson will now reconfigure itself
if needed, which is required if we change or move around meson files, as otherwise
meson tends to explode spectacularly in hard to debug ways.
https://mesonbuild.com/Release-notes-for-1-7-0.html#test-targets-no-longer-built-by-default
Instead of listing dependencies manually for the default tools tree,
let's reuse the prepare scripts from the build image. To make this work,
the sync script has to be configured for the tools tree as well so that
it's invoked both when building the tools tree and for the regular image,
otherwise, when doing the first build in a fresh checkout, the sync script
won't have executed yet as sync scripts for the regular images are executed
after building the default tools tree.
Instead of not creating the test at all, let's always create test but
simply mark them as skipped as this is more observable than simply not
creating the test at all.
This test only works if the image was built as root. Since that's
impossible to check as meson generally runs before we build the image,
let's use whether meson is run as root as a proxy.
If we don't need an initrd, let's not waste time in one. We have to
gate this by distributions that have the necessary kernel modules to
make this work as builtin modules, hopefully we can expand the list in
the future.
This is a required first step before testing and it's not specifically
mentioned in the doc. This tripped me up for a while, so let's save the
trouble for the next person.
Currently, to run the integration tests, it's still necessary to
install various other build tools besides meson: A compiler, gperf,
libcap, ... which we want to avoid in CI systems where we receive
prebuilt systemd packages and only want to test them. Examples are
Debian's autopkgtest CI and Fedora CI. Let's make it possible for
these systems to run the integration tests without having to install
any other build dependency besides meson by extracting the logic
required to run the integration tests with meson into a separate
subdirectory and adding a standalone top-level meson.build file which
can be used to configure a meson tree with as its only purpose running
the integration tests.
Practically, we do the following:
- all the integration test directories and integration-test-wrapper.py
are moved from test/ to test/integration-tests/.
- All the installation logic is kept out of test/integration-tests/ or
any of its subdirectories and moved into test/meson.build instead.
- We add test/integration-tests/standalone/meson.build to run the
integration tests standalone. This meson file includes
test/integration-tests via a cute symlink hack to trick meson into
including a parent directory with subdir().
- Documentation is included on how to use the new standalone mode.
Currently, to run the integration tests, it's still necessary to
install various other build tools besides meson: A compiler, gperf,
libcap, ... which we want to avoid in CI systems where we receive
prebuilt systemd packages and only want to test them. Examples are
Debian's autopkgtest CI and Fedora CI. Let's make it possible for
these systems to run the integration tests without having to install
any other build dependency besides meson by extracting the logic
required to run the integration tests with meson into a separate
subdirectory and adding a standalone top-level meson.build file which
can be used to configure a meson tree with as its only purpose running
the integration tests.
Practically, we do the following:
- all the integration test directories and integration-test-wrapper.py
are moved from test/ to test/integration-test/.
- All the installation logic is kept out of test/integration-test/ or
any of its subdirectories and moved into test/meson.build instead.
- We add test/integration-test/standalone/meson.build to run the
integration tests standalone. This meson file includes
test/integration-test via a cute symlink hack to trick meson into
including a parent directory with subdir().
- Documentation is included on how to use the new standalone mode.
- TEST-64-UDEV-STORAGE and TEST-85-NETWORK are changed to generate separate
units for each testcase to make them behave more like the other integration
tests.
The debug logs has lots of "About to execute /some/path (null)". This
occurs when the args array is empty. Instead, only print "(null)" if
we failed with oom.
Having strv_skip() return NULL makes this pleasant to write without repeating
strv_isempty() a few times.
strv_skip was written to carefully return the original array, but this turns
out to be an unnecessary complication. After the previous patch, no caller
cares about the distinction between NULL and { NULL }, but various callers need
to wrap the process the returned value with strv_isempty(), sometimes more than
once. Let's always return NULL for an empty result to allow callers to be
simplified.
Except for one place, they are only used by test-watch-pid. Let's also
use manager_get_unit_by_pidref() and friends in the test, and drop the
_pid() variants.
It confused the hell of me, that if pid1 crashes in an mkosi system run
from the build tree there's no coredump kept. Because mkosi configures
journal storage for coredumps, but that's not going to work for pid1 or
journald. Hence use external storage for these two even if everything
else is stored in the journal.