This also adds bus_assert_return() as an variant of assertion.
With this change, more code blocks are checked by coccinelle,
thus the test become slightly slower. So the timeout is extended.
Also, as checking exec_invoke() takes so long, let's skip it.
Note, previously the function was skipped due to parse error caused by
unknown cleanup attributes. So, the coverage is not decreased by the
skip.
Provides a Tokio-like #[tokio::main] entry point for binaries that want
to run their main function inside a fiber on a default sd_event loop.
DEFINE_MAIN_FUNCTION_FIBER(impl) mirrors DEFINE_MAIN_FUNCTION but routes
impl through a new run_main_fiber() helper, which:
- allocates the default sd_event,
- enables exit-on-idle so the loop terminates once all event sources
drain (structured concurrency: impl is expected to cancel and reap
whatever it spawned before returning),
- spawns impl as a fiber named after program_invocation_short_name,
- installs SIGINT/SIGTERM handlers that cancel the main fiber (and
disable themselves so the loop can go idle once the fiber unwinds),
- runs sd_event_loop and propagates impl's return value via
sd_future_result, normalising -ECANCELED to 0 since that just
represents an orderly signal-driven shutdown.
With DNSSEC on, resolved can't validate anything until the clock is
correct,
and without an RTC the only thing that fixes the clock is talking to the
NTP servers we're trying to resolve.
On glibc the timesyncd unit sets SYSTEMD_NSS_RESOLVE_VALIDATE=0 and
nss-resolve turns that into a per-query flag, which breaks the
chicken/egg. musl and systems not using nss-resolve have no NSS, so
nothing
reads it there and we're stuck.
So talk to resolved directly when it's there, and pass
SD_RESOLVED_NO_VALIDATE until we've synced the clock ourselves. Lookups
after that are validated normally, which is better than what we get from
nss. If resolved isn't around we keep using getaddrinfo().
Tested on musl in qemu with the RTC set to 2020 and DNSSEC=yes.
timesyncd syncs when it couldn't before, while `resolvectl query` still
fails with signature-expired, so the "relaxation" is scoped to only
timesyncd.
Once the clock is synced subsequent timesyncd resolver queries no longer
include the flag to disable validation.
fixes#20235
PID, UID, and GID are converted by sending struct ucred, however, TID
was not converted. Let's convert TID if corresponding pidfd exists, and
discards TID otherwise.
Fixes 4c7af7d9d1.
Since kernel v6.19, ioctl(PIDFD_GET_INFO) can return the set of
supported flags when PIDFD_INFO_SUPPORTED_MASK is specified.
This allows checking whether, e.g., PIDFD_INFO_COREDUMP_SIGNAL is
supported by the running kernel.
PID, UID, and GID are converted by sending struct ucred, however,
TID was not converted. Let's convert TID if corresponding pidfd exists,
and discards TID otherwise.
Fixes 4c7af7d9d1.
The connect callback is called after sd_varlink_server_add_connection()
succeeds. Do not call the disconnect callback for connections that have
not been established yet.
This makes json_stream_attach_fds() and json_stream_connect_fd_pair()
leave the passed file descriptors with the caller on failure. Callers
should call TAKE_FD() only after a successful call.
Also make qmp_client_connect_fd() always take ownership of the passed
file descriptor, including on failure. Previously, ownership of the
passed file descriptor on failure was unclear and depended on where
the function failed.
verb_chid(), verb_blame() and verb_identify_tpm2() all render their
output via table_print_with_pager() with arg_json_format_flags, so JSON
output has been implemented for them since each verb was introduced.
None of them was ever added to the verb allowlist
that gates --json=, so e.g. systemd-analyze chid --json=pretty failed
with:
Option --json= is only supported for security, inspect-elf,
dlopen-metadata, ...
This adds them to the allowlist and the error message. After a sweep of
src/analyze/ for arg_json_format_flags, these are the only remaining
verbs that render through it but were not allowlisted.
has-tpm2 is deliberately not included: verb_has_tpm2() defers to
verb_has_tpm2_generic(), which writes plain text via printf() and has no
JSON support, so accepting --json= there would silently ignore it. The
table_print_with_pager() call in analyze-has-tpm2.c
belongs to verb_identify_tpm2(), which is what got allowlisted instead.
The chid gap went unnoticed because its TEST-65-ANALYZE coverage is
guarded behind a check for SMBIOS board_vendor and a non-container
environment, so it only runs on bare-metal/VM runners.
- pcrextend: Fix use-after-free/double-free error in pcrextend_pcr_now
With SignInitrdPCRs=disabled in mkosi the TPM/PCR services are broken
which triggers the error path in the varlink call which means that we
get parameters set in the response. The wrong ownership assumption when
looking at the reply with _cleanup_ set caused a memory corruption that
surfaced in systemd-sysext with an ABRT.
This is a common mistake done with the API, fix it by not setting
_cleanup_(sd_json_variant_unrefp).
- pkcs7: Correct error handling for pkcs7_extract_signers
The lack of error handling for sym_i2d_X509_NAME/sym_i2d_ASN1_INTEGER
means that we get a NULL iovec that will cause an assertion failure
later. The use of regular free for OpenSSL is probably okay but since
the allocator can differ, one should use OPENSSL_free.
Add error handling and do an explicit copy instead of ownership transfer
between possibly different allocators.
Syncing acpi/pnp data from uefi.org has been broken for a while due to
changes to the server trying to block scrapers. Set custom user agent
string to be allowed to connect.
For some of us building image based operating systems with
`systemd-sysupdate` it's useful to have UKI filenames that encode
`IMAGE_VERSION` (and architecture). For example
`SimonOS_45.20260805.0_x86-64.efi`.
Currently to do this I have to manually post-process around the `.efi`
produced by `60-ukify` because it is named
`$ENTRY_TOKEN-$KERNEL_VERSION.efi`. It'd be very useful if I could skip
that step and instead have the image built directly without this
post-processing step; then extract the UKI and /usr partitions and plop
them onto my update server. It makes the build much more "install RPMs
into a tree and you're done" (barring other things `60-ukify` currently
can't do but I have follow-ups for those in mind).
This PR adds a knob to `install.conf` to let users specify a custom
format for the output filename for both UKI's and BLS entries produced
by `kernel-install`.
It accepts the following specifiers:
- `%e`: entry token
- `%v`: kernel version being installed
- Several common specifiers
The default is %e-%v, which is the current behavior. With
`entry_name_format=%M_%A_%a`, an OS with `IMAGE_ID=SimonOS` and
`IMAGE_VERSION=1.0` would get moved to `SimonOS_1.0_x86-64.efi`.
The resolved name is exported as `$KERNEL_INSTALL_ENTRY_NAME` for shell
plugins. Both `90-uki-copy.install` and `90-loaderentry.install` are
updated to use it, with a fallback to `$ENTRY_TOKEN-$KERNEL_VERSION` for
compatibility with older kernel-install versions.
TEST-92-TPM2-SWTPM requires about 15 minutes on GitHub,
if it starts at the very end, the total CI run simply waits for
the test finished, and wastes the last 15 minutes.
Starting earlier should slightly improve the performance.
We currently blindly send the configured reload signal (e.g. SIGHUP or
SIGUSR1) to the main service PID for Type=notify-reload units, even if
the service hasn't installed a userspace handler. This can lead to
invoking unintended default behavior (typically process termination) in
daemons which later deprecate and remove their reload handler.
This is a real problem we have seen in production on multiple occasions.
In one particularly egregious instance, a production distributed storage
service had a large percentage of its nodes all terminate at once when
sent a reload signal. In this case a signal handler had been removed,
but another place still sending the signal was missed.
To mitigate this, introduce two new checks for Type=notify-reload
services:
1. On READY=1: When the service first sends READY=1 during initial
startup, we check for the handler. If it's missing, the service startup
is failed with SERVICE_FAILURE_PROTOCOL. This enforces the contract that
services *must* install their handler before signalling readiness.
2. On reload: Immediately before sending the reload signal, we check
again. If the handler is now missing, we log a warning but still send
the signal. This preserves the requested operator action while making
the missing handler visible.
The startup check catches definite static misconfiguration before the
service is accepted as ready. The reload check is advisory because the
service has already started successfully, but warns if its handler later
disappears. Together these provide a best-effort safety net while
preserving the agreed reload semantics.
- --strict=/--full moved to the OPTION_LONG() parser framework that
replaced getopt in the meantime
- the is-supported commit is dropped, main grew that verb independently.
That also gets rid of the early tpm2_support() gate that broke CI back
then, and TEST-70-TPM2 runs with a software TPM these days anyway
- special_glyph() → glyph() renames
- the log table PCR filter needs an EVENT_LOG_RECORD_IS_PCR() guard now
that the event log has NV-index records
Explicitly call label_ops_post() where necessary with specific
arguments. Previously, regardless if fopen_tmpfile_linkable_at()
success, label_ops_post() was called but its argument was heavily
conditionalized. Let's call it both on failure and success cases
with specific arguments. This should be easy to read.
This also
- moves variable declarations where used,
- drops unnecessary boolean flag call_label_ops_post.
No functional change. Just reafactoring.
Hopefully silence CID#1664328, though it is false-positive.
This is useful when writing coredump pattern. But the logic itself is
quite generic. Let's add the helper in our basic library.
Preparation for later change.
Previously, bpf_restrict_fsaccess_prepare() is called twice in
bpf_restrict_fsaccess_setup(). One by through
bpf_restrict_fsaccess_supported() and one by itself directly.
In PID1, bpf_restrict_fsaccess_prepare() was only called by
bpf_restrict_fsaccess_setup(), hence it is not necessary to exist as a
separated function.
bpf_restrict_fsaccess_prepare() loads BPF program(s), hence it is
slightly slow operation.
Let's avoid redundant loading of BPF programs by merging
bpf_restrict_fsaccess_supported() into bpf_restrict_fsaccess_setup().
Co-authored-by: Eric Curtin <eric.curtin@docker.com>
This merges prepare_restrict_fs_bpf() and bpf_restrict_fs_supported()
into bpf_restrict_fs_setup().
Previously, bpf_restrict_fs_supported() was only called in
manager_new() and bpf_restrict_fs_cleanup(). However, it is not
necessary to call it in bpf_restrict_fs_cleanup(), as if the feature is
not supporetd, manager->restrict_fs is always NULL. In manager_new()
the function was always called with bpf_restrict_fs_setup(). Hence,
it is not necessary to keep bpf_restrict_fs_supported() and
bpf_restrict_fs_setup() as separated functions.
This also drops unnecessary '#if HAVE_LIBBPF' condition in
manager_new(), as bpf_restrict_fs_setup() is well defined also when
libbpf support is disabled.
Follow-up for c99678eeda.
This updates systemd-tmpfiles in two small areas:
- Reject non-empty argument fields for tmpfiles.d line types that do not
consume the argument field, instead of warning and silently ignoring
them.
- Let `r` and `R` tmpfiles.d entries honor the `Age` field when
`systemd-tmpfiles --clean` is used. The existing `--remove` behavior
remains unconditional.
The completed TODO entries are removed, and NEWS/man page documentation
is updated for the visible behavior changes.
Error returned from security_compute_create_raw() means that kernel
couldn't compute target context. Very likely because file context is not
known to the policy, i.e. security.selinux xattr contains some garbage
value and we are running in permissive mode, otherwise returned context
would be "unlabeled_t" instead of getting an error.
mac_selinux_get_create_label_from_exe() is used to figure out create
label for socket units and we fail to start the socket if we can't
figure out that label.
However, it may be necessary to start some sockets in order to get to
the point when we launch the service that relabels (in permissive mode)
the entire filesystem and reboots.
Quote each serialized exec directory entry, and use extract flags
compatible with config_parse_exec_directories() when deserializing.
This allows paths containing spaces and escaped characters to round-trip
correctly.
Fixes#41853.
Replaces #42686.
Since 1166f4472d the API bus setup
and the subscriber coldplug happen only once the asynchronous GetId
reply is processed by the event loop. After a daemon-reexec,
manager_dispatch_dbus_queue() runs before subscribers were registered
and consumed send_reloading_done, so the one-shot Reloading(false)
signal was never sent.
Clients that wait for this signal to detect that a reexec finished time out.
Track the pending setup and hold the flag until the reply handler has
re-added the subscriptions.
Also affects v261.2 via backport 26f3717e27f6f08347adf851c605d5fe1f52ac57.
- sysupdate: In the auto-enable service, don't enable all features
The auto-enable service should activate suggested components and
features but enabled all features which includes the default components
unsuggested features and any unsuggested features of the suggested
components. This is unexpected behavior and we rather want this service
to be limited to suggested features.
Switch the service flag to suggested and make the wording more explicit
in the man page. Also fix the wrong statement that it operates on
enabled components, it operates on all components, also explicitly
disabled ones.
- sysupdate: Change disabling with
--component-suggested/--feature-suggested
The disabling of features or components with the flag
--component-suggested/--feature-suggested didn't disable the suggested
ones but instead disabled all other ones. This is rather unintuitive due
to how the flags are named and also not really needed because the
intended reconciliation outcome can instead be done by first disabling
everything and then enabling the suggested ones again which is easier to
reason about. For components the tricky part is that they default to
enabled and thus it's better to have the disable/enable commands with
--component-suggested operate only on suggested ones instead of touching
others like "legacy" components that don't explicity say whether they
are enabled and suggested or not.
Make running disablement of components/features with
--component-suggested/--feature-suggested undo a previous enablement
with the same flags. Document how one can align the system to only use
suggested components/features and not anything else by doing it in two
steps, first disabling everything and then enabling suggested ones. This
also makes it clearer now that all components that are not explicitly
enabled nor suggested will be disabled then.
Fixes the following failure on Fedora 44:
```
TEST-58-REPART.sh[932]: Executing mkfs command: /usr/bin/mkfs.erofs -U 45745a56-aa2f-4619-8ca7-9cb63667c2ae -zlz4hc,level=3 /dev/loop0 /var/tmp/.#reparteb739e8b8cae7b70
TEST-58-REPART.sh[932]: Successfully forked off '(mkfs)' as PID 933.
TEST-58-REPART.sh[933]: ==933==ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD.
TEST-58-REPART.sh[932]: '(mkfs)' failed with exit status 1.
```
## Summary
Closes#18280.
`systemd-homed` currently writes fscrypt v1 policies, which bind the
master key to the calling process's keyring. This means files in a
homed-managed directory aren't readable when accessed through a
container bind mount, a different mount namespace, or by any process
other than the one that first unlocked the home. Reading the file from a
context that has the key first warms the page cache, but the underlying
problem remains.
v2 policies (Linux 5.4+) route the master key through the filesystem
keyring, via `FS_IOC_ADD_ENCRYPTION_KEY` /
`FS_IOC_REMOVE_ENCRYPTION_KEY`, so the key is visible to every process
accessing the filesystem.
This PR switches `systemd-homed` to v2 by default and keeps existing v1
homes working.
## Changes
**`shared/crypto-util`**: Add `kdf_hkdf_derive` (HKDF, RFC 5869) wrapper
around OpenSSL's `EVP_KDF` "HKDF", alongside the existing SSKDF/KBKDF
helpers.
**`homed/fscrypt`**:
- Read the existing policy via `FS_IOC_GET_ENCRYPTION_POLICY_EX`,
falling back to the legacy ioctl on pre-5.4 kernels.
- `HomeSetup` now carries a full `struct fscrypt_key_specifier` instead
of a bare 8-byte descriptor. Slot decryption derives either the v1
descriptor (double SHA-512) or the v2 identifier (HKDF-SHA512 with the
kernel's info string) from the unwrapped volume key and compares against
the policy.
- Install the master key the right way per version: `add_key("logon",
...)` to thread+user keyrings for v1, `FS_IOC_ADD_ENCRYPTION_KEY` for
v2.
- `home_flush_keyring_fscrypt` opens the image directory, reads the
policy version, and either calls `FS_IOC_REMOVE_ENCRYPTION_KEY` (v2) or
walks the user keyring (v1).
- New homes default to v2; fall back to v1 only when the kernel rejects
v2.
The on-disk slot xattr format is unchanged - the volume key is the same,
only how it binds to the directory changes. There is no v1 -> v2
migration; existing v1 homes continue to unlock, rekey, and deactivate
as before.
Previously, specifying multiple stacked netdevs of the same type required
repeating the corresponding setting, e.g.:
```
[Network]
VLAN=vlan_10
VLAN=vlan_20
VLAN=vlan_30
```
With this change, the same configuration can be written as:
```
[Network]
VLAN=vlan_10 vlan_20 vlan_30
```
Specifying an empty string now also clears all previously assigned stacked
netdevs.
Closes#43103.
During early boot, interfaces may be renamed frequently, which can lead to
caching the driver name of a different interface. Invalidate the cached
driver whenever an interface rename is detected so it can be re-read using
the new name.
Follow-up for #42545.
Fixes#43099.
I noticed that the use of sed in the `80-systemd-osc-context.sh` was
unnecessary, and upon writing a replacement in pure bash and testing it,
actually buggy. While in there, I also spotted some other minor things
that might be worth doing.
Getting rid of fork+exec for doing sed is probably the biggest win, but
there are still quite a few subshell invocations (that only do fork, not
exec). I haven't measured the overhead of those, but it seems that we
could get rid of those as well if we want.
Another thing I wonder about is whether we should emit an end= marker on
shell exit. There's no guaranteed way of doing it. Just as everything
else, we could get killed before getting a chance to do it. But also,
unlike PROMPT_COMMANDS, there's no "at_exit" array to hook into. Still,
we could ask if there is a 'trap exit' hook installed, and if not,
install one ourselves; if the user's bashrc subsequently overrides that,
so be it (though .bash_logout would be more appropriate).
This partially reverts 13ce62caba.
Sometimes, the kernel passes non-safe characters in uevent files,
such as the UNIQ= property for USB serial devices.
Instead of rejecting the entire uevent file, let's only ignore the
specific key-value pairs that contain non-safe characters.
Fixes#43008.
The modern hwdb.bin format contains the filenames of the input data that
makes up the database. This is useful but in offline builds where --root
is used, the filenames are the full build paths including the specified
root. This introduces build paths and thus information leakage and
non-reproducible data.
Solve this by stripping the root prefix off the original path when
passing to import_file.
Nowadays, varlink is used to control systemd-udevd. Let's drop the
legacy socket.
Note, the existence of /run/udev/control socket is widely used in both
our code and external projects. Also, the dependency to
systemd-udevd-control.socket is widely used in many projects.
Hence, we need to create a symlink to the socket file and .socket unit
file.
nspawn itself does not require to control udevd process.
Only necessary points are
- udevd is available, and
- we are in the main network namespace.
Let's check them explicitly.
This also makes the check is skipped when we are talking to mountfsd, as
the check is pointless in that case.