The helper reaches a user manager with the uid@ machine transport. That
transport runs systemd-run, which opens a PAM login session for the user.
In that session, systemd-stdio-bridge connects to the user's D-Bus broker.
rpm runs the helper once per package scriptlet. A large transaction therefore
opens many login sessions for every logged-in user. The operations also fail
whenever the user's D-Bus broker is not running.
The user manager accepts connections from root on its private socket, and
systemctl --user uses the same socket. Connect to
/run/user/UID/systemd/private directly with bus_connect_user_systemd_by_uid().
The user owns /run/user/UID. The function therefore refuses a socket that the
user does not own or that a process of another user listens on. Otherwise a
user could point the helper at the private socket of the system manager.
cleanup() is only called via 'trap cleanup EXIT', which newer shellcheck
versions report as SC2329 rather than SC2317. Disable both, like the other
test scripts do.
One of the fundamental counters we need to cover in metrics are
packet/byte counters on network interfaces. Let's add this.
We do this separately from networkd, to not unnecessarily affect
networkd operations.
While systemd-report is conceptually designed to provide freshness
guarantees without nonces (for example via TPM clock, TSA or generation
counters), it sometimes is useful to provide a nonce, when talking
directly and synchronously to a node, instead of asynchronously.
Hence, let's just extend the Generate Varlink calls with a nonce
argument.
The birth time of the root inode of the file system backing /var/ is a
good approximation of when the system was deployed, i.e. when its
persistent file system was created. If /var/ is not a mount point of its
own, use the root file system instead.
The metric is skipped if the file system does not record birth times.
And while we are at it, let's also expose CLOCK_REALTIME, all in nsec
accuracy.
(The realtime clock is also included in the report header, but in
calendar format with second granularity.)
The Process lines in systemctl status join argv with spaces, making
multi-word arguments ambiguous and empty arguments invisible.
Use quote_command_line() with SHELL_ESCAPE_EMPTY to retain argument
boundaries. Leave the formatted string NULL for an empty argv vector so
that strna() prints n/a. Cover whitespace, empty arguments and literal
dollar signs in TEST-26-SYSTEMCTL.
Fixes#43938.
The "pcr" component currently only contains the attested PCR digest.
Whilst the PCR values can be reconstructed from the accompanying log,
the "nvpcr" components already contain NvPCR values. This adds the
attested PCR values alongside the TPM quote for consistency.
In tree mode, list-dependencies prints a unit once for every path that
leads to it. The "units" strv is only a stack of the current path, used
for cycle detection, so every time a unit shows up again its
dependencies (a GetAll() call) and its active state (a Get() call) were
fetched from the manager again. With --all the number of paths grows far
faster than the number of units: on a stock Fedora desktop,
"list-dependencies --all sockets.target" prints 30152 lines for roughly
260 distinct units, and spends about 20 seconds doing synchronous D-Bus
round trips for units it had already asked about.
unit_get_dependencies() now also reads ActiveState, which comes with the
same GetAll() reply, and returns both in a UnitDependencyInfo.
list-dependencies keeps these in a single hashmap keyed by unit name and
takes every unit's state from there, so each distinct unit costs exactly
one D-Bus call per invocation. The dependency list is sorted once when it
is cached. With --all this also halves the number of D-Bus calls compared
to querying dependencies and state separately (311 -> 157 messages for
sockets.target).
While at it, append_unit_dependencies() no longer passes an
uninitialized pointer to strv_extend_strv_consume() when
unit_get_dependencies() fails; it now skips the unit instead.
The output is unchanged; the only difference is that the state of a unit
that appears several times now comes from a single snapshot instead of
being re-read on every occurrence.
list-dependencies --all sockets.target 20.45s -> 0.12s
list-dependencies --all basic.target 25.03s -> 0.20s
--plain, --type= and --state= already visit each unit only once and are
unaffected.
Messages on the private bus have no sender. As it is now, when a job is
canceled through it, as "systemctl cancel" does when run as root, we
pass a NULL name to sd_bus_track_contains(), which fails an
assert_return(). In developer builds, that makes PID 1 abort. Otherwise
it's only logged at debug level, and we consult polkit, as we should.
Let's only check whether the sender owns the job if there is a sender.
Jobs enqueued through the private bus aren't tracked anyway.
The only test of systemd-update-helper is part of the rpm upgrade test,
which only runs on rpm-based distributions and only covers removing units
from a frozen user manager. Test the commands on the system manager and on
the user manager of a lingering user, the per-user disable on removal,
template units, a symlink in place of the private socket of a user manager,
and a frozen user manager.
This prog is still labelled as experimental and we didn't
have a way to disable its build. With the addition of this option,
all experimental components can be disabled.
This PR just gives an error if the profile used to attach a portable
service doesn't exist.
The work is basically in "portable: fail attach/reattach if the profile
does not exist"
A small fix found along the way is in "portable: log the right error
when the profile lookup fails"
I put below the description of "portable: fail attach/reattach if the
profile does not exist"
---
Before this commit, if you attach a portable service using a profile
that doesn't exist, it just doesn't add the profile dropin and no
warning nor anything is shown:
$ portablectl attach -p nonexistent xxx
(Matching unit files with prefix 'xxx'.)
Created directory /etc/systemd/system.attached.
Created directory /etc/systemd/system.attached/xxx-capsule.service.d.
Written
/etc/systemd/system.attached/xxx-capsule.service.d/20-portable.conf.
Copied /etc/systemd/system.attached/xxx-capsule.service.
Created symlink /etc/portables/xxx.raw → /var/lib/portables/xxx.raw.
$ ls /etc/systemd/system.attached/xxx-capsule.service.d/
20-portable.conf
The 10-profile.conf is not added.
If no profile is attached, the /run bind mount is not added and then lot
of things inside fail in ways that don't make sense.
This patch just makes portable_attach() and reattach check the profile
exists. If it doesn't exist, it shows this error now:
# portablectl -p doesntexists reattach xxx
(Matching unit files with prefix 'xxx'.)
ReattachImage failed: Profile 'doesntexists' does not exist, refusing.
(Available profiles are: default, nonetwork, strict, trusted)
In reattach we do it early, before detach, so we don't detach and then
fail to attach it and leave the service detached.
Please note that we don't change install_profile_dropin(), as that skips
non-existing profiles because that is done at the unit type level and
it's okay if it doesn't exist for some unit types. For example,
/usr/lib/systemd/portable/profile/trusted/ ships a service.conf, but not
timer.conf, socket.conf, etc.
vmspawn creates the ephemeral overlay of an --image= in the runtime directory,
which is usually on tmpfs, and falls back to a memfd. The guest's writes
therefore use up host memory. Create the overlay next to the image after
following symlinks. nspawn puts its ephemeral copy of an image there too, and
vmspawn puts the snapshot for --directory= next to the directory.
If the image is a block device, use the directory for large temporary files
instead, because /dev/ is a devtmpfs. Do the same if the image is a deleted
file or a memfd, because a deleted file or a memfd has no directory. Also do
the same if the overlay cannot be created next to the image, for example
because the directory is read-only.
Disable copy-on-write on the overlay, because small random writes fragment a
copy-on-write file on btrfs.
Hopefully fixes the following race:
```
TEST-17-UDEV.sh[11202]: + for i in /dev/block/*
TEST-17-UDEV.sh[11202]: + udevadm lock --device /dev/block/252:3 --print
TEST-17-UDEV.sh[11778]: /dev/vda
TEST-17-UDEV.sh[11202]: + udevadm lock --device /dev/block/252:3 true
TEST-17-UDEV.sh[11780]: Device '/dev/vda' is currently locked, waiting…
TEST-17-UDEV.sh[11782]: + udevadm lock --device /dev/block/252:3 false
TEST-17-UDEV.sh[11202]: + for i in /dev/block/*
TEST-17-UDEV.sh[11202]: + udevadm lock --device /dev/block/259:1 --print
TEST-17-UDEV.sh[11787]: Failed to find whole block device for '/dev/block/259:1': No such file or directory
```
Add an integration test that exercises .device unit state transitions for
loopback block device partitions and their udev devlinks (SYMLINK+=),
together with services bound to them via BindsTo=.
The following cases are covered:
- basic setup with daemon-reload/reexec (testcase_loopdev_basic),
- devlink updates on change events (testcase_loopdev_change_devlink),
- devlink priority changes reassigning shared devlinks
(testcase_loopdev_change_devlink_priority),
- SYSTEMD_READY toggling (testcase_loopdev_systemd_ready),
- ID_PROCESSING handling during daemon-reload/reexec
(testcase_loopdev_id_processing),
- switch-root emulation (testcase_loopdev_switching_root),
- device removal during switching-root
(testcase_loopdev_remove_on_switching_root).
Add an integration test that exercises .device unit state transitions
for a network interface and its SYSTEMD_ALIAS device units, together
with services bound to them via BindsTo=.
The following cases are covered:
- basic setup with daemon-reload/reexec (testcase_netif_basic),
- alias updates on change events (testcase_netif_change_alias),
- SYSTEMD_READY toggling (testcase_netif_systemd_ready),
- ID_PROCESSING handling during daemon-reload/reexec
(testcase_netif_id_processing),
- switch-root emulation (testcase_netif_switching_root),
- device removal during switching-root
(testcase_netif_remove_on_switching_root),
- interface renaming (testcase_netif_rename_*).
This includes reproducers for issues #35329 and #43767.
- Only download distro systemd packages in mkosi.prepare, set up the
devel sytemd packages in mkosi.postinst so that they're always up to
date.
- Use systemd-analyze for version comparisons
- Add test to make sure units are stopped on downgrade
- Add test to make sure removing a package with a frozen user session
doesn't blow up
Let's rewrite the script in C, which gives us access to
libsystemd-shared for implementing future features.
We immediately make use of libsystemd-shared to add a new --stdin
option, allowing the script to read units to operate on as unit file
paths from stdin. This allows using the script with various hook/trigger
features provided by package managers such as pacman and rpm.
As a bonus, the amount of forks is reduced by not shelling out to
systemctl multiple times which could matter for a script that's
executed quite a few times during every dnf system upgrade.
We had the concept of subtests in our integration test suit for some
time, but it wasn't wired to meson test, which only understood the top
level test cases. With this change, we use the TAP protocol to report
subtest results to meson so meson gets understanding of it and subtest
results become part of the native meson output.
Switch the integration tests to meson's TAP protocol, fed by the
wrapper's --tap output. Subtest results and skips now show up in meson's
own reporting, e.g. "OK ... 5 subtests passed", instead of being visible
only inside the test log.
Signed-off-by: Paul Meyer <katexochen0@gmail.com>
With --tap, report per-subtest results extracted from the forwarded
journal as a TAP stream on stdout: one point per subtest, skips as SKIP
directives, and skip gates as a skipped plan. Tests without subtest
records collapse to a single point mirroring the overall verdict, and a
failure no subtest accounts for is reported as a point of its own.
Signed-off-by: Paul Meyer <katexochen0@gmail.com>
Sign a system report through the io.systemd.Report pipeline in the
SNP guest and export the resulting signed report to the host. The host
takes the role of a remote verifier: the tsm signature record must carry
the digest of the signed report bytes, that digest must be embedded in
the REPORT_DATA field of the enclosed SNP attestation report, and the
attestation report must verify against the AMD certificate chain with
snpguest, which is added to the Fedora test image. Certificates must be
pre-provisioned on the host in a sirectory named 'snp-certs' and bound
into the test container via $TEST_BIND_DIRS.
Signed-off-by: Paul Meyer <katexochen0@gmail.com>
Directories listed in $TEST_BIND_DIRS are bound read-only into the
boot-mode container at /work/<basename>, so a test can consume
host-provided data that cannot be baked into the image, such as a
machine's pre-provisioned AMD certificates for coco attestation.
Signed-off-by: Paul Meyer <katexochen0@gmail.com>
Route the streamed test output (the mkosi console) and coredump to
stderr. Diagnostics belong there anyway, and it frees stdout to carry
machine-readable results for meson's TAP protocol.
Signed-off-by: Paul Meyer <katexochen0@gmail.com>
Log one structured record per executed subtest under a fixed MESSAGE_ID,
so the integration test wrapper can extract per-subtest results from the
forwarded journal. Best-effort: without a reachable journal the records
are simply absent.
Signed-off-by: Paul Meyer <katexochen0@gmail.com>
The metric list is built with conf_files_list_strv(), but each metric's
value is then looked up again by walking report_files_dirs[] by hand,
and the two disagreed whenever an earlier directory had an entry that is
not a regular file:
- conf_files_list_strv() skipped such an entry and listed the one from
a later directory, so the metric was advertised by Describe();
- file_metric_generate() only moved on to the next directory on
-ENOENT, so it hit the non-regular entry, logged a warning and
produced nothing.
The practical case is masking a vendor-supplied entry with a symlink to
/dev/null: the metric kept being described, was never listed, and every
scrape logged "Failed to open ..., skipping: File descriptor in bad
state".
Honour masks in the enumeration via CONF_FILES_FILTER_MASKED_BY_SYMLINK,
as other conf dirs do, and make the lookup skip non-regular entries the
same way the enumeration does. Document the masking in the man page and
cover both cases in TEST-74-AUX-UTILS.report.
vmspawn never used `aio=io_uring` for disks, even when QEMU supports it.
Commit 1a7b6fd9dd added a blockdev probe node named `__io_uring_probe`.
QEMU rejects that name ("Invalid node-name"), as node names have to
start with a letter. The probe then reported io_uring as unsupported.
Use a valid name, following the "vmspawn-" prefix of the other node names.
Check the multi-drive test's debug log for rejected node names to catch
this and similar issues in the future.
Signed-off-by: Martin Pitt <martin@amutable.com>