Obserbed with GCC-11 on Ubuntu.
```
In file included from ../src/shared/format-table.h:7,
from ../src/bless-boot/bless-boot.c:11:
../src/bless-boot/bless-boot.c: In function ‘verb_set’:
../src/basic/log.h:187:27: error: ‘source2’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
187 | ? log_internal(_level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
| ^~~~~~~~~~~~
../src/bless-boot/bless-boot.c:458:40: note: ‘source2’ was declared here
458 | const char *target, *source1, *source2;
| ^~~~~~~
In file included from ../src/shared/format-table.h:7,
from ../src/bless-boot/bless-boot.c:11:
../src/basic/log.h:187:27: error: ‘source1’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
187 | ? log_internal(_level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
| ^~~~~~~~~~~~
../src/bless-boot/bless-boot.c:458:30: note: ‘source1’ was declared here
458 | const char *target, *source1, *source2;
| ^~~~~~~
In file included from ../src/shared/format-table.h:7,
from ../src/bless-boot/bless-boot.c:11:
../src/basic/log.h:187:27: error: ‘target’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
187 | ? log_internal(_level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
| ^~~~~~~~~~~~
../src/bless-boot/bless-boot.c:458:21: note: ‘target’ was declared here
458 | const char *target, *source1, *source2;
| ^~~~~~
cc1: all warnings being treated as errors
```
crypto-util: make OpenSSL UI API symbols optional during dlopen
Previously, if systemd was built with OpenSSL UI support, it would fail
to load libcrypto at runtime if the library lacked UI support, requiring
a recompilation of systemd to fix.
Let's relax this strict requirement by making the UI methods optional
during dlopen(). openssl_ui_supported() is added to dynamically check
if all required UI symbols were successfully loaded.
crypto-util: allow loading private keys from engine/provider without UI support
OpenSSL UI is not a mandatory feature to load private keys from an engine
or a provider. Let's allow loading private keys even if OpenSSL UI is not
supported.
Note that even if OPENSSL_NO_UI_CONSOLE is set, the type UI_METHOD is
always defined. Hence, the `#ifndef` condition in the definition of
struct OpenSSLAskPasswordUI is unnecessary and can be dropped.
crypto-util: make OpenSSL ENGINE API symbols optional during dlopen
If systemd is compiled with OpenSSL 3 headers but executed in an environment
where OpenSSL 4 (libcrypto.so.4) is loaded, dlopen_many_sym_or_warn() will
fail because OpenSSL 4 completely removes the deprecated ENGINE API. This
breaks the ability to dynamically fallback and seamlessly upgrade OpenSSL
without recompiling systemd.
To fix this, drop the ENGINE API symbols from the mandatory DLSYM_ARG() list.
Instead, try to load them via DLSYM_OPTIONAL() after the library is opened.
load_key_from_engine() is updated to check for their presence and return
-EOPNOTSUPP if the loaded OpenSSL version does not provide them.
Yu Watanabe [Tue, 30 Jun 2026 15:39:53 +0000 (00:39 +0900)]
crypto-util: drop manual endianness handling in rsa_pkey_from_n_e()
Currently, rsa_pkey_from_n_e() uses architecture-specific `#if` branches
and memdup_reverse() to handle big-endian RSA components (n and e)
before passing them directly to OSSL_PARAM_construct_BN().
We can simplify this by parsing the raw big-endian bytes into BIGNUMs
first using BN_bin2bn(), which natively expects big-endian data. We
can then push these BIGNUMs into OSSL_PARAM_BLD. This delegates the
data format handling entirely to OpenSSL and successfully removes the
platform-specific code.
Drop memstream and i2d_PUBKEY_fp(). We can simply use i2d_PUBKEY()
which automatically allocates the necessary buffer for us.
Note that dropping the secure erase (erase_and_freep()) in favor of
OPENSSL_free() is intentional and safe, as the buffer only holds
public key material which does not need to be securely wiped.
Yu Watanabe [Tue, 30 Jun 2026 15:00:11 +0000 (00:00 +0900)]
crypto-util: use correct cleanup function for OpenSSL buffers
Buffers allocated by OpenSSL must be freed with OPENSSL_free().
Fortunately, we do not enable the secure heap, so OPENSSL_free()
is currently equivalent to free(), but let's fix this for correctness.
Yu Watanabe [Tue, 30 Jun 2026 12:05:50 +0000 (21:05 +0900)]
resolved: migrate ECDSA verification to OpenSSL 3 EVP API
OpenSSL 3.0 deprecated low-level Elliptic Curve (EC) key manipulation
functions (EC_KEY, EC_POINT, EC_GROUP) and direct signature verification
functions like ECDSA_do_verify().
This commit modernizes dnssec_ecdsa_verify_raw() by transitioning to the
provider-aware EVP API:
* Uses OSSL_PARAM arrays and EVP_PKEY_fromdata() to construct the EC
public key directly from the raw octet string and curve name, avoiding
deprecated EC_POINT parsing.
* Converts the raw R and S signature components into a DER-encoded ASN.1
signature using i2d_ECDSA_SIG(), as required by the modern EVP API.
* Uses EVP_PKEY_verify() for the actual signature validation.
Additionally, this drops an outdated TODO comment waiting for raw ECDSA
support in the EVP API, as well as the deprecated warning suppression
macros and fallback code blocks. Unit tests for ECDSA are now run
unconditionally.
Yu Watanabe [Tue, 30 Jun 2026 08:00:27 +0000 (17:00 +0900)]
resolved: migrate RSA key construction to OpenSSL 3 EVP API
OpenSSL 3.0 deprecated low-level key manipulation functions and direct
access to RSA structures (such as RSA_new(), RSA_set0_key(), and
RSA_size()).
This commit modernizes dnssec_rsa_verify_raw() by replacing these
deprecated functions with the provider-aware EVP API:
* Uses OSSL_PARAM_BLD and EVP_PKEY_fromdata() to construct the RSA
public key directly from the modulus and exponent BIGNUMs.
* Replaces RSA_size() with EVP_PKEY_get_size().
Consequently, the workaround macros suppressing deprecated warnings
(DISABLE_WARNING_DEPRECATED_DECLARATIONS) and the conditional fallback
blocks (#if !defined(OPENSSL_NO_DEPRECATED_3_0)) are no longer needed
and have been dropped. Unit tests are also updated to run unconditionally.
dongshengyuan [Tue, 30 Jun 2026 10:10:49 +0000 (18:10 +0800)]
coredumpctl: use break instead of continue for time bound checks
When iterating journal entries with --until (forward scan) or --since
(reverse scan), the code used continue instead of break after crossing
the time boundary.
Since sd_journal_seek_realtime_usec() is called before the loop to
position at the start of the range, sd_journal_next()/previous()
returns entries in monotonically increasing/decreasing time order.
Once an entry's timestamp exceeds arg_until (or falls below arg_since
in reverse), all subsequent entries will also be out of range.
Using continue caused the entire remaining journal to be scanned
unnecessarily. journalctl uses break for the identical pattern in
src/journal/journalctl-show.c.
Kai Lüke [Mon, 15 Jun 2026 13:11:41 +0000 (15:11 +0200)]
vmspawn/nspawn: Always use a per-machine runtime subdirectory
Some state files were prefixed with the machine name which protected
against collisions when running concurrent machines in a systemd unit
with RuntimeDirectory= set. However, the socket files tpm.sock and
control were not, which caused a race. Prefixing these socket files
does not work because the path gets too long when both the subdirectory
and the socket file within it get unique identifiers.
Instead of prefixing all files, we can rather always create a
subdirectory and use simple names within in. This makes paths shorter
in the normal case and protects against races with RuntimeDirectory=
were instead of directly reusing RUNTIME_DIRECTORY we also create the
normal per-machine subdirectory. Since this here is about runtime state
it should not impact any running VMs/containers. The ssh-proxy looks
only at the normal case and does not support RUNTIME_DIRECTORY, so no
impact there as well.
meson: fix fs.exists() check for fuzz corpus samples
Commit 8355eb6e11 ("meson: Check if files returned by git ls-files
actually exist") checks the paths printed by git ls-files, which are
relative to the project root, with fs.exists(), which resolves them
relative to the test/fuzz subdirectory. As a result, every corpus
sample was silently skipped, and only the generated directives tests
were registered. Resolve the paths against the project source root
instead.
Daan De Meyer [Mon, 29 Jun 2026 12:08:27 +0000 (12:08 +0000)]
compress: handle ZSTD_CONTENTSIZE_UNKNOWN when decompressing blobs
The zstd blob decompression code assumed ZSTD_getFrameContentSize() always
returns the decompressed size, which holds for the journal and coredump blobs
systemd compresses itself with the one-shot ZSTD_compress(). Frames produced by
the streaming API, however, don't record the decompressed size in their header,
so ZSTD_getFrameContentSize() returns ZSTD_CONTENTSIZE_UNKNOWN. Per the zstd
documentation this is not an error, but decompress_blob_zstd() and
decompress_startswith_zstd() bailed out with -EBADMSG regardless.
This broke kexec of kernel images compressed with 'zstd' (e.g. zstd -22), whose
ZBOOT payload is decompressed via decompress_blob().
Treat only ZSTD_CONTENTSIZE_ERROR as fatal and, when the size is unknown, grow
the output buffer as we stream the frame out instead of relying on the recorded
size. Add a regression test that feeds a streaming-compressed (hence
unknown-size) zstd frame through decompress_blob() and decompress_startswith().
Philip Withnall [Thu, 2 Jul 2026 13:06:50 +0000 (14:06 +0100)]
docs: Update memory pressure docs for latest GLib support for it
As of GLib 2.90.0 (not yet released), GLib will fully support the spec,
including the `MEMORY_PRESSURE_WATCH` and `MEMORY_PRESSURE_WRITE`
environment variables, which it did not support previously.
See https://gitlab.gnome.org/GNOME/glib/-/merge_requests/5046
Paul Meyer [Sun, 7 Jun 2026 17:07:41 +0000 (19:07 +0200)]
ukify: show all sections and profiles in inspect JSON output
The JSON output keyed every section by name, so a UKI with repeated
sections only showed the last one: in a multi-profile UKI all but one
.profile/.cmdline/.pcrsig were dropped, as were extra .dtbauto/.efifw.
Report the shared base sections by name at the top level (so .cmdline
etc. stay where they were), each profile as its own by-name object under
a new "_profiles" array, and the alternative-set sections (.dtbauto,
.efifw) as arrays.
Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Paul Meyer <katexochen0@gmail.com>
Paul Meyer [Thu, 2 Jul 2026 07:28:35 +0000 (09:28 +0200)]
boot: measure SMBIOS via non-TPM runtime measurements
In commit 29c6d1c12549 ("boot: measure select SMBIOS objects
explicitly") we added an explicit SMBIOS measurement in systemd-boot
and systemd-stub, covering cases where firmware doesn't measure SMBIOS
itself. measure_smbios() bailed unless a TPM was present, so it skipped
the measurement on confidential guests that only expose a CC
measurement protocol (e.g. Intel TDX RTMRs).
We can have much higher expectations of the virtual firmware used for
confidential computing, and the firmware is attested, so we can expect
it to always measure SMBIOS in this case. We still do our own
measurement to get a measurement structure similar to that of
non-confidential guests, and as another line of defense.
Michael Vogt [Tue, 30 Jun 2026 16:08:47 +0000 (18:08 +0200)]
firstboot: add new systemd.firstboot=headless mode
This adds a new systemd.firstboot=headless mode. It differs from the
existing systemd.firstboot=no mode in that it still performs the
non-interactive auto-configuration that requires no user input (such
as selecting the only installed locale, or applying settings provided
via credentials), and only skips the prompts that would otherwise
block waiting for user input. In contrast, =no disables that
auto-configuration along with the prompts.
The option is also honoured by homectls firstboot logic and
systemd-cryptenroll, where headless behaves the same as no
(because the is no auto-configuration).
bpf-restrict-fs: use a 32-bit magic key on big-endian too
The inner map is created with a uint32_t key, but the update passed
&magic[i] where magic is a (possibly 64-bit) statfs_f_type_t. On
little-endian the low 32 bits happen to be read; on big-endian 64-bit
(s390x, ppc64 BE) the zero high word is read instead, so every
filesystem collides on key 0 (the allow/deny selector) and
RestrictFileSystems= is silently broken. Pass a truncated copy.
core/scope: don't assert when start is retried during cgroup chown
While a delegated scope waits for the async cgroup chown helper it sits
in SCOPE_START_CHOWN (UNIT_ACTIVATING). unit_start() forwards to
->start() while activating, so scope_start() could be re-entered in
that state and trip assert(s->state == SCOPE_DEAD), aborting PID 1.
Treat SCOPE_START_CHOWN as already-starting instead.
core: donate the fdset to do_reexecute() to avoid a double free
do_reexecute() freed the FDSet on the switch-root/soft-reboot fallback
but the caller's copy stayed live, so main() freed it again if every
fallback exec then failed. Donate the fdset instead: pass it with
TAKE_PTR() and take ownership via a _cleanup_ local, freeing it exactly
once on every exit path.
Shihao Ren [Tue, 30 Jun 2026 12:30:50 +0000 (20:30 +0800)]
run: refuse --no-block when combined with --scope
In the systemd-run --scope mode, --no-block has no actual effect and will
be silently ignored. Therefore, this combination is explicitly rejected to
reduce confusion for users when using it.
shared/install: give the borrowed name back before bailing on error
In the unmask path, when install_changes_add() fails the borrowed
*name was not handed back via TAKE_PTR() before returning, so
install_info_clear() freed the caller's strv entry, leaving a dangling
pointer that is double-freed at the caller's strv_free().
Chris Coulson [Tue, 2 Jun 2026 13:48:55 +0000 (14:48 +0100)]
tpm2-setup: Create and persist an endorsement key
This updates systemd-tpm2-setup to create and persist an endorsement
key if there isn't one already. For each supported EK template profile,
it will read the EK certificate from its NV index if there is one.
When there is an EK certificate present, a primary key is created using
the corresponding template. If the resulting EKpub matches the public
key in the certificate, the created EK is persisted and the process is
complete.
The low-range templates and the high-range RSA 2048/3072 and ECC NIST
P256/P384 storage templates are supported, as detailed in section
5.3 of the "TCG EK Credential Profile For TPM Family 2.0" spec v2.7.
High-range templates are preferred because these permit EK usage without
requiring knowledge of the authorization value for the endorsement
hierarchy, meaning that, like with the SRK, it is possible to restrict
the usage of the endorsement hierarchy whilst still permitting use of
the persistent EK.
The EK is always persisted at handle 0x81010001. This handle is
reserved in Table 2 of the "TCG TPM v2.0 Provisioning Guidance" spec
v1.0r1.0, although this is only a recommendation. This
handle is within the block of handles reserved for endorsement
primary keys in the "Registry of Reserved TPM 2.0 Handles and
Localities" spec v1.2r1.00. Section 2.3.2 of this specification also
makes a suggestion that there should be a relationship between the EK
certificate NV index and a corresponding persistent EK handle by
using handles at the same offsets within their respective ranges.
However, this contradicts the provisioning guidance spec which reserves
0x81010001 when there isn't a certificate at 0x01c00001. For simplicity,
I've chosen to use a single handle for the EK regardless of which profile
it is created with.
The "TCG EK Credential Profile For TPM Family 2.0" spec also provides a
way for endorsement keys to be certified with non-standard templates by
storing the template in a NV index. This is also supported.
The EK creation is not executed with tpm2-setup --early, as there's no
need for it to be created so early, unlike with the SRK. I also haven't
stored EKpub in /var/lib/systemd like with the SRKpub, as I'm not sure
there will be a use case for this yet.
A follow-up PR may be needed to add some internal helpers to make use
of the persisted EK, as use of low-range EKs requires a policy session.
High-range EKs can be used with a HMAC session because they have the
userWithAuth attribute set and we are creating them with an empty
authorization value.
Michael Vogt [Thu, 21 May 2026 14:57:15 +0000 (16:57 +0200)]
core: add absolute-path properties to varlink StartTransient
Similar to PR#42360 this commit adds missing properties for
absolute path handling in io.systemd.Unit.StartTransient for
the `Exec` context and a macro helper to share the common code.
Note that RootHashPath, RootHashSignaturePath need custom apply
functions because the varlink name "RootHashPath" differs from the
name that needs to be written into the unit file ("RootHash=")
and the iovec must be cleared.
In various cases we'll touch the same directories multiple times with
mtools: for example the /loader/ dir itself. Unfortunately mtools' mmd
does not implement a graceful "-p" switch like mkdir, but will do some
interactive name clash thing instead. We can turn this off via "-Ds
-DS", so let's do that. But that's not enough since the tool will still
fail with a non-explanatory exit status of 1. This hence ignores that
failure and proceeds anyway, under the assumption that failures to
create a directory will sooner or later be detected anyway once the
directory is to be populated and turns out not be existing because the
creation failed.
This makes some integration test/mkosi invocations work
non-interactively again.
Paul Meyer [Tue, 30 Jun 2026 11:30:08 +0000 (13:30 +0200)]
core: trust SMBIOS credentials under Intel TDX
SMBIOS OEM strings are host-controlled and normally distrusted by PID1
in confidential VMs. Under TDX, however, the SMBIOS table (including
Type 11) is measured into RTMR0 by the firmware (TDVF), so a remote
verifier can detect host tampering with credentials delivered this
way. Accept them there, while keeping fw_cfg distrusted as those
items are not measured even on TDX.
This lets systemd-vmspawn deliver credentials to TDX guests via the
normal SMBIOS path, unlike SNP which requires the initrd cpio channel.
Add more shutdown timestamps and preserve via LUO (#42671)
Add more shutdown timestamps, export them via D-Bus/Varlink, use them in
`systemd-analyze time`, and preserve them across kexec via LUO. This is
useful to measure reboot performance with added measurement points and
more granular intervals.
Paul Meyer [Mon, 29 Jun 2026 10:59:45 +0000 (12:59 +0200)]
tsm-report: error on empty report
Previously we would return a valid signature containing the empty
outblob, which is undesirable. In other cases where we cannot query a
report because the guest doesn't support it we currently return an
empty response so the signature aggregator in systemd-report silently
skips it. In this case, we have everything we need to actually get a
report on the guest side, but the host isn't providing us with the
quote, so we fail.
Paul Meyer [Mon, 29 Jun 2026 10:21:02 +0000 (12:21 +0200)]
vmspawn: allow TDX guest to connect to host QGS
To query a TD quote, the TDX guest must connect to the Quote Generation
Service (QGS), a SGX enclave running on the host. We check if the
service is exposed via a well-known unix socket, then pass that socket
or a fallback well-known vsock address to QEMU.
Paul Meyer [Fri, 26 Jun 2026 09:57:29 +0000 (11:57 +0200)]
vmspawn: add Intel TDX confidential VM support
Wire up --coco=tdx alongside the existing SEV-SNP path. TDX requires KVM
on x86_64, a raw TDVF firmware loaded via -bios (no pflash/NVRAM split),
kernel-irqchip=split, and the "host" CPU model since QEMU rejects named
models. Sets up the tdx-guest object and confidential-guest-support=tdx0.
TDX measurement is different from QEMU's kernel-hashes injection: TDX
provides runtime measurements via RTMRs, so the initial measurement only
covers the firmware, which then measures the rest of the boot chain into
those RTMRs (done by OVMF today). Therefore a restriction to direct
kernel boot isn't required either.
Luca Boccassi [Fri, 26 Jun 2026 12:57:27 +0000 (13:57 +0100)]
core: deserialize soft-reboot shutdown timestamps into previous-* fields
Until now the SHUTDOWN_START/FINISH timestamps were carried across a
soft-reboot in the same fields, so afterwards they described the
previous boot rather than the current one, mixing current- and
previous-boot data in the same set. Mirror what is now done on kexec
and move them into the PREVIOUS_SHUTDOWN_* fields on deserialization.
Also reset local timestamps for events that rerun (eg: generators,
units loading, etc) on soft-reboot and switch-root.
Nick Rosbrook [Fri, 26 Jun 2026 14:00:21 +0000 (10:00 -0400)]
test: reduce number of disks in TEST-64-UDEV-STORAGE-simultaneous_events on Debian/Ubuntu
This test never finishes in Ubuntu autopkgtest with the current values,
and is currently skipped all together on Debian. When running on either,
reduce the number of disks to make the test more reliable.
dongshengyuan [Wed, 24 Jun 2026 05:01:32 +0000 (13:01 +0800)]
sd-journal: rate-limit tail timestamp refresh during iteration
journal_file_read_tail_timestamp() is called unconditionally in
next_beyond_location() for every file on every iteration step,
resulting in O(N x files) volatile mmap reads. For large queries
like 'journalctl -n 1000000' this makes the command unusably slow
(~5 minutes on systems with many journal files).
Rather than suppressing the call entirely (which would make the
inotify path fully load-bearing for cross-boot ordering), rate-limit
it to at most once per second per file. This reduces the overhead
from O(N x files) to O(T x files) where T is the iteration time in
seconds, while still providing periodic refresh as a fallback for
any missed inotify events and keeping cross-boot ordering
reasonably fresh.
Embed a RateLimit struct in JournalFile for this purpose.
Measured improvement on a real system: 5:24 -> 2:39 (-51%) for
'journalctl -n 1000000'.
Shihao Ren [Tue, 30 Jun 2026 06:18:14 +0000 (14:18 +0800)]
man: fix wrong KillUserProcesses= default in systemd-run(1)
systemd-run(1) hard-coded "the default" wording for KillUserProcesses=, but the
actual compile-time default is determined by the -Ddefault-kill-user-processes=
meson build option, which distributions set differently at packaging time.
Luca Boccassi [Mon, 29 Jun 2026 17:07:01 +0000 (18:07 +0100)]
ptyfwd: avoid touching forwarder after exit drain
on_exit_event() can synchronously drain buffered data through
shovel_force(). If that completes the drain, pty_forward_done() runs
the hangup handler and may free the forwarder, so do not call
pty_forward_done() again afterwards.
[ 25.052879] TEST-74-AUX-UTILS.sh[909]: ==909==ERROR: AddressSanitizer: heap-use-after-free on address 0x7ccc8a5e0b41 at pc 0x7efc8cde106e bp 0x7ffd668629b0 sp 0x7ffd668629a8
[ 25.053136] TEST-74-AUX-UTILS.sh[909]: READ of size 1 at 0x7ccc8a5e0b41 thread T0
[ 25.092784] TEST-74-AUX-UTILS.sh[909]: #0 0x7efc8cde106d in pty_forward_done ../src/src/shared/ptyfwd.c:187
[ 25.093920] TEST-74-AUX-UTILS.sh[909]: #1 0x7efc8cdedba1 in on_exit_event ../src/src/shared/ptyfwd.c:904
[ 25.094148] TEST-74-AUX-UTILS.sh[909]: #2 0x7efc8d375eff in source_dispatch ../src/src/libsystemd/sd-event/sd-event.c:4301
[ 25.095074] TEST-74-AUX-UTILS.sh[909]: #3 0x7efc8d378032 in dispatch_exit ../src/src/libsystemd/sd-event/sd-event.c:4431
[ 25.095295] TEST-74-AUX-UTILS.sh[909]: #4 0x7efc8d37e932 in sd_event_dispatch ../src/src/libsystemd/sd-event/sd-event.c:4896
[ 25.095467] TEST-74-AUX-UTILS.sh[909]: #5 0x7efc8d37fc8c in sd_event_run ../src/src/libsystemd/sd-event/sd-event.c:4971
[ 25.095647] TEST-74-AUX-UTILS.sh[909]: #6 0x7efc8d3800ad in sd_event_loop ../src/src/libsystemd/sd-event/sd-event.c:4992
[ 25.097174] TEST-74-AUX-UTILS.sh[909]: #7 0x56049b541aba in start_transient_service ../src/src/run/run.c:2479
[ 25.097403] TEST-74-AUX-UTILS.sh[909]: #8 0x56049b552a65 in run ../src/src/run/run.c:3288
[ 25.097569] TEST-74-AUX-UTILS.sh[909]: #9 0x56049b552cb0 in main ../src/src/run/run.c:3291
[ 25.097780] TEST-74-AUX-UTILS.sh[909]: #10 0x7efc8b882300 in __libc_start_call_main (/lib64/libc.so.6+0x7d300) (BuildId: 830c94f480c13d9b01dc65a1035310882136094a)
[ 25.097952] TEST-74-AUX-UTILS.sh[909]: #11 0x7efc8b882417 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x7d417) (BuildId: 830c94f480c13d9b01dc65a1035310882136094a)
[ 25.098139] TEST-74-AUX-UTILS.sh[909]: #12 0x56049b51cf54 in _start (/usr/bin/systemd-run+0x19f54) (BuildId: 0daacdb9f20151f3517312ee99e489a9b8f4989c)
[ 25.098316] TEST-74-AUX-UTILS.sh[909]: 0x7ccc8a5e0b41 is located 193 bytes inside of 2384-byte region [0x7ccc8a5e0a80,0x7ccc8a5e13d0)
[ 25.099202] TEST-74-AUX-UTILS.sh[909]: freed by thread T0 here:
[ 25.099410] TEST-74-AUX-UTILS.sh[909]: #0 0x7efc8e76420f in free.part.0 (/lib64/libasan.so.8+0x16420f) (BuildId: 173395e60f171589489dde2b7a156d0ae380734b)
[ 25.099557] TEST-74-AUX-UTILS.sh[909]: #1 0x7efc8cdf14d1 in pty_forward_free ../src/src/shared/ptyfwd.c:1122
[ 25.099691] TEST-74-AUX-UTILS.sh[909]: #2 0x56049b535328 in pty_forward_handler ../src/src/run/run.c:1952
[ 25.100063] TEST-74-AUX-UTILS.sh[909]: #3 0x7efc8cde138c in pty_forward_done ../src/src/shared/ptyfwd.c:196
[ 25.100197] TEST-74-AUX-UTILS.sh[909]: #4 0x7efc8cdec757 in shovel ../src/src/shared/ptyfwd.c:813
[ 25.101144] TEST-74-AUX-UTILS.sh[909]: #5 0x7efc8cdecc1f in shovel_force ../src/src/shared/ptyfwd.c:828
[ 25.102273] TEST-74-AUX-UTILS.sh[909]: #6 0x7efc8cdedb82 in on_exit_event ../src/src/shared/ptyfwd.c:899
[ 25.103564] TEST-74-AUX-UTILS.sh[909]: #7 0x7efc8d375eff in source_dispatch ../src/src/libsystemd/sd-event/sd-event.c:4301
[ 25.103712] TEST-74-AUX-UTILS.sh[909]: #8 0x7efc8d378032 in dispatch_exit ../src/src/libsystemd/sd-event/sd-event.c:4431
[ 25.104081] TEST-74-AUX-UTILS.sh[909]: #9 0x7efc8d37e932 in sd_event_dispatch ../src/src/libsystemd/sd-event/sd-event.c:4896
[ 25.104954] TEST-74-AUX-UTILS.sh[909]: #10 0x7efc8d37fc8c in sd_event_run ../src/src/libsystemd/sd-event/sd-event.c:4971
[ 25.105160] TEST-74-AUX-UTILS.sh[909]: #11 0x7efc8d3800ad in sd_event_loop ../src/src/libsystemd/sd-event/sd-event.c:4992
[ 25.105310] TEST-74-AUX-UTILS.sh[909]: #12 0x56049b541aba in start_transient_service ../src/src/run/run.c:2479
[ 25.105454] TEST-74-AUX-UTILS.sh[909]: #13 0x56049b552a65 in run ../src/src/run/run.c:3288
[ 25.105572] TEST-74-AUX-UTILS.sh[909]: #14 0x56049b552cb0 in main ../src/src/run/run.c:3291
[ 25.106136] TEST-74-AUX-UTILS.sh[909]: #15 0x7efc8b882300 in __libc_start_call_main (/lib64/libc.so.6+0x7d300) (BuildId: 830c94f480c13d9b01dc65a1035310882136094a)
[ 25.106263] TEST-74-AUX-UTILS.sh[909]: #16 0x7efc8b882417 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x7d417) (BuildId: 830c94f480c13d9b01dc65a1035310882136094a)
[ 25.106385] TEST-74-AUX-UTILS.sh[909]: #17 0x56049b51cf54 in _start (/usr/bin/systemd-run+0x19f54) (BuildId: 0daacdb9f20151f3517312ee99e489a9b8f4989c)
[ 25.106792] TEST-74-AUX-UTILS.sh[909]: previously allocated by thread T0 here:
[ 25.106957] TEST-74-AUX-UTILS.sh[909]: #0 0x7efc8e76515f in malloc (/lib64/libasan.so.8+0x16515f) (BuildId: 173395e60f171589489dde2b7a156d0ae380734b)
[ 25.108013] TEST-74-AUX-UTILS.sh[909]: #1 0x7efc8cddebed in malloc_multiply ../src/src/basic/alloc-util.h:92
[ 25.108188] TEST-74-AUX-UTILS.sh[909]: #2 0x7efc8cdee47b in pty_forward_new ../src/src/shared/ptyfwd.c:955
[ 25.108324] TEST-74-AUX-UTILS.sh[909]: #3 0x56049b538700 in run_context_setup_ptyfwd ../src/src/run/run.c:2130
[ 25.108472] TEST-74-AUX-UTILS.sh[909]: #4 0x56049b5419f9 in start_transient_service ../src/src/run/run.c:2465
[ 25.109152] TEST-74-AUX-UTILS.sh[909]: #5 0x56049b552a65 in run ../src/src/run/run.c:3288
[ 25.109311] TEST-74-AUX-UTILS.sh[909]: #6 0x56049b552cb0 in main ../src/src/run/run.c:3291
[ 25.109450] TEST-74-AUX-UTILS.sh[909]: #7 0x7efc8b882300 in __libc_start_call_main (/lib64/libc.so.6+0x7d300) (BuildId: 830c94f480c13d9b01dc65a1035310882136094a)
[ 25.109847] TEST-74-AUX-UTILS.sh[909]: #8 0x7efc8b882417 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x7d417) (BuildId: 830c94f480c13d9b01dc65a1035310882136094a)
[ 25.110760] TEST-74-AUX-UTILS.sh[909]: #9 0x56049b51cf54 in _start (/usr/bin/systemd-run+0x19f54) (BuildId: 0daacdb9f20151f3517312ee99e489a9b8f4989c)
[ 25.110911] TEST-74-AUX-UTILS.sh[909]: SUMMARY: AddressSanitizer: heap-use-after-free ../src/src/shared/ptyfwd.c:187 in pty_forward_done
[ 25.111054] TEST-74-AUX-UTILS.sh[909]: Shadow bytes around the buggy address:
[ 25.111213] TEST-74-AUX-UTILS.sh[909]: 0x7ccc8a5e0880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[ 25.111378] TEST-74-AUX-UTILS.sh[909]: 0x7ccc8a5e0900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[ 25.111520] TEST-74-AUX-UTILS.sh[909]: 0x7ccc8a5e0980: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[ 25.112210] TEST-74-AUX-UTILS.sh[909]: 0x7ccc8a5e0a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
[ 25.112399] TEST-74-AUX-UTILS.sh[909]: 0x7ccc8a5e0a80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
[ 25.112767] TEST-74-AUX-UTILS.sh[909]: =>0x7ccc8a5e0b00: fd fd fd fd fd fd fd fd[fd]fd fd fd fd fd fd fd
[ 25.112901] TEST-74-AUX-UTILS.sh[909]: 0x7ccc8a5e0b80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
[ 25.113789] TEST-74-AUX-UTILS.sh[909]: 0x7ccc8a5e0c00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
[ 25.113906] TEST-74-AUX-UTILS.sh[909]: 0x7ccc8a5e0c80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
[ 25.114046] TEST-74-AUX-UTILS.sh[909]: 0x7ccc8a5e0d00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
[ 25.114159] TEST-74-AUX-UTILS.sh[909]: 0x7ccc8a5e0d80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
[ 25.114278] TEST-74-AUX-UTILS.sh[909]: Shadow byte legend (one shadow byte represents 8 application bytes):
[ 25.114400] TEST-74-AUX-UTILS.sh[909]: Addressable: 00
[ 25.115099] TEST-74-AUX-UTILS.sh[909]: Partially addressable: 01 02 03 04 05 06 07
[ 25.115246] TEST-74-AUX-UTILS.sh[909]: Heap left redzone: fa
[ 25.115365] TEST-74-AUX-UTILS.sh[909]: Freed heap region: fd
[ 25.115483] TEST-74-AUX-UTILS.sh[909]: Stack left redzone: f1
[ 25.115618] TEST-74-AUX-UTILS.sh[909]: Stack mid redzone: f2
[ 25.115882] TEST-74-AUX-UTILS.sh[909]: Stack right redzone: f3
[ 25.116735] TEST-74-AUX-UTILS.sh[909]: Stack after return: f5
[ 25.116857] TEST-74-AUX-UTILS.sh[909]: Stack use after scope: f8
[ 25.116974] TEST-74-AUX-UTILS.sh[909]: Global redzone: f9
[ 25.117108] TEST-74-AUX-UTILS.sh[909]: Global init order: f6
[ 25.117257] TEST-74-AUX-UTILS.sh[909]: Poisoned by user: f7
[ 25.118128] TEST-74-AUX-UTILS.sh[909]: Container overflow: fc
[ 25.118288] TEST-74-AUX-UTILS.sh[909]: Array cookie: ac
[ 25.118433] TEST-74-AUX-UTILS.sh[909]: Intra object redzone: bb
[ 25.118546] TEST-74-AUX-UTILS.sh[909]: ASan internal: fe
[ 25.118684] TEST-74-AUX-UTILS.sh[909]: Left alloca redzone: ca
[ 25.118792] TEST-74-AUX-UTILS.sh[909]: Right alloca redzone: cb
[ 25.119282] TEST-74-AUX-UTILS.sh[909]: Command: systemd-run --quiet --pty -- bash -c echo PTY_FORWARD_READY; exec sleep 60
[ 25.119395] TEST-74-AUX-UTILS.sh[909]: ==909==ABORTING
dongshengyuan [Tue, 30 Jun 2026 01:47:22 +0000 (09:47 +0800)]
boot/random-seed: create \loader\ dir if missing when seeding
When the random seed file doesn't exist but we have good entropy
(seeded_by_efi=true), we attempt to create it. This requires a handle
to the \loader\ directory, which may not exist on systems using
UKI+EFISTUB without systemd-boot installed.
Obtain the directory handle by first trying a read-only open; if that
returns EFI_NOT_FOUND, create the directory. We deliberately avoid
requesting write access on an already-present directory because some
firmware implementations return EFI_INVALID_PARAMETER for a
WRITE|CREATE open on an existing directory — this would be logged at
LOG_ERR and abort seed creation on systems where \loader\ exists but
random-seed does not (the normal systemd-boot layout).
Once a handle to \loader\ is obtained, open the seed file relative to
that handle rather than using the full path from root.
Introduced-by: c0e7046c17 ("boot: log about RO I/O errors at debug level.") Fixes: #42801 Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
Luca Boccassi [Mon, 29 Jun 2026 14:05:51 +0000 (15:05 +0100)]
env-util: ensure NUL termination of the replace_env_argv() output array
The output array is allocated with new() and left uninitialized, but a
bare unset "$VAR" token expands to nothing and writes no terminator.
When such a token leads or is the only word, the returned strv is left
without a trailing NULL.
dongshengyuan [Tue, 30 Jun 2026 09:13:10 +0000 (17:13 +0800)]
resolvectl: fix JSON reply cleanup in varlink_dump_dns_configuration
varlink_call_and_log() does not hand out a new reference for the reply
object, so the caller should not unref it. The _cleanup_(sd_json_variant_unrefp)
on reply was therefore wrong from the start.
The original TAKE_PTR(reply) was working around this incorrect cleanup
by preventing it from firing, but that left reply's refcount one too
high after sd_json_variant_ref(v) incremented the parent's count.
Fix by dropping _cleanup_(sd_json_variant_unrefp) from the reply
variable declaration entirely, as suggested by Lennart Poettering.
Luca Boccassi [Fri, 19 Jun 2026 22:48:21 +0000 (23:48 +0100)]
core/shutdown: add more shutdown timestamps
We already record when shutdown.target is initiated (ShutdownStart).
This adds a few more measuring points during shutdown: when
shutdown.target completes (i.e., all units stopped), when the shutdown
binary starts executing, and immediately before it hands off to the
kernel.
Obviously these are immediately lost upon reboot. But they will later
be wired in LUO so they get preserved on kexec, and can be inspected,
which is very useful for performance measurements.
dongshengyuan [Tue, 30 Jun 2026 09:11:32 +0000 (17:11 +0800)]
exec-invoke: fix wrong errno in log_error_errno for setenv failure
When setenv("CREDENTIALS_DIRECTORY") fails, log_error_errno() was
called with the stale return value of exec_context_get_credential_directory()
(which is >= 0 on success) instead of errno.
The %m in the format string correctly expands from libc's errno, so
the human-readable log message was unaffected. However, the structured
journal field ERRNO= received an incorrect value (0 or positive),
making automated log analysis and alerting on this failure unreliable.
Ronan Pigott [Mon, 29 Jun 2026 19:14:58 +0000 (12:14 -0700)]
run: do not munge user.slice with --slice-inherit
When using --slice-inherit, setting arg_slice would inadvertently munge
user.slice into the current user slice, usually producing a slice name
like user-1000-user.slice. This is treated as a user-UID slice by
user-.slice.d/10-defaults.conf, resulting in a strange description:
literally "User slice for UID user" (instead of an actual user UID).
Keep arg_slice empty when using --slice-inherit so that we actually
inherit from the relevant slice instead of a munged version.
portable: leave room for trailing NUL in metadata receive buffer
receive_portable_metadata() reads each item into a stack buffer of
PATH_MAX + NAME_MAX + 2 bytes, passes the full sizeof() as the recv
iovec length, and then NUL-terminates with iov_buffer[n] = 0. recvmsg()
can return n equal to the buffer size, so the terminator is written one
byte past the end.
Grow the buffer by one byte and cap the iovec at sizeof - 1, so a full
record is still received and the trailing NUL always fits, matching the
coredump-receive.c reader.
dongshengyuan [Mon, 29 Jun 2026 05:24:51 +0000 (13:24 +0800)]
man: document that $XDG_CONFIG_HOME affects environment.d lookup path
Align the documentation with the actual behavior: if $XDG_CONFIG_HOME is
set to an absolute path in the user service manager environment, it takes
precedence over the default ~/.config/ when locating environment.d files.
Also note the bootstrapping limitation that variables defined inside
environment.d files are not yet available when the generator runs.