The immediate impulse for this change is the fedora scriptlet which called:
/usr/lib/systemd/systemd-update-helper install-system-units cryptsetup-pre.target cryptsetup.target getty@.service ... system-systemd\x2dcryptsetup.slice system-systemd\x2dveritysetup.slice ...
which called
systemctl preset cryptsetup-pre.target cryptsetup.target getty@.service ... system-systemd\x2dcryptsetup.slice system-systemd\x2dveritysetup.slice ...
which threw an error that system-systemdx2dcryptsetup.slice does not exist
and did nothing at all. (The backslash is consumed by the shell.)
The obvious fix here is to figure out more levels of escaping… But we should
do something more robust in such cases.
If we fail in processing of a single unit, let preset all continue processing
units, report the failure through 'changes'. At the end, return failure. In
general, for operations which operate on a list of units specified by the user,
fail the whole operation if any of the individual operations failed. The only
operation where we don't do this is 'preset-all'.
$ SYSTEMD_LOG_LEVEL=debug build/systemctl --root=/ preset asdf1.servie asdf2.path; echo $?
Cannot find unit asdf1.servie.service.
Cannot find unit asdf2.path.
Failed to preset unit: Unit asdf1.servie.service does not exist
Failed to preset unit: Unit asdf2.path does not exist
1
While at it, fix double logging in the manager: dump_unit_changes() already
logs about errors, so the manager should only log on success.
This partially reverts a4f0e0da3573a10bc5404142be8799418760b1d1. The
intent was good, we gather the errors, but we have no mechanism to
propagate the result, so the gathered result was ignored. In 'changes'
we can only report errors for specific units. If reading of the
directory fails, we might just as well report the error immediately.
This isn't great, but it's better then ignoring the errors. In practice,
failing halfway in this manner is unlikely, since it'd mean that the fs
is corrupted or something like that. We might as well return immediately
on such catastrophic errors.
sd-bus: allow receiving messages with MSG_CTRUNC set (#40089)
In the event that we can't receive all of the fds from the message
(which can happen for a number of reasons including LSM denials or
hitting the fd limit of the process) the kernel will set the MSG_CTRUNC
flag. Through our use of recvmsg_safe() we've been treating this as a
fatal error, which will result in dropping the connection.
Let's dial that back a bit: we can receive the message, but when the
user attempts to access the missing fds via sd_bus_message_read_basic()
we can return the (existing) error code of -EBADMSG to indicate that the
fd is missing.
We can do this by using recvmsg() directly, and relaxing some of the
checks on message creation: when (and only when) we have received
MSG_CTRUNC we allow a smaller than expected (per the header) number of
fds to be present. The error check in sd_bus_message_read_basic() was
already there so we don't need to do anything about that.
This puts the receiver of the message into a difficult situation: you
can call sd_bus_message_read_basic() as often as you want but as long as
it keeps returning -EBADMSG it won't progress through the message and
you won't be able to close whatever container you're in. That means
that the user will probably need to abandon processing the message
anyway. So why not just drop the message up front? This approach is
more likely to yield a useful error message, which will be invaluable
for people trying to track down problems caused by LSM denials.
Michael Vogt [Mon, 26 Jan 2026 18:25:50 +0000 (19:25 +0100)]
vmspawn: keep stderr fd connected when running ssh-keygen
When vmspawn executes ssh-keygen it currently hides all std{out,err}.
This is not ideal when errors happen, so this commit tweaks the
code to include stderr in the output.
My use case is that I recently ran into the issue that inside a
`mkosi box` my systemd-homed user was not available so ssh-keygen
errored with `No user exists for uid 1000` [0] but that error was
not visible, only the generic:
`'/usr/bin/ssh-keygen' failed with exit status 255.`
was displayed.
This also adds FORK_REOPEN_LOG to the pidref_safe_fork flags,
thanks to Mike Yuan for the suggestion.
[0] Arguably this is also an issue in ssh-keygen because it does
not need to do the user lookup when `-f /path/` is passed.
Sriman Achanta [Tue, 27 Jan 2026 06:11:35 +0000 (01:11 -0500)]
hwdb: Add extended SteelSeries Arctis headset device support (#40479)
Add USB device IDs for additional SteelSeries Arctis headset models to
the sound card hardware database. This extends support for the complete
Arctis lineup including newer models.
Newly added device IDs:
- Arctis 7 P (0x12d5)
- Arctis Pro (0x1290)
- Arctis Nova 3 (0x12ec)
- Arctis Nova 3 P (0x2269)
- Arctis Nova 3 X (0x226d)
- Arctis Nova 5 (0x2232)
- Arctis Nova 5 X (0x2253)
- Arctis Nova 7 Rev2 (0x2258)
- Arctis Nova 7 Diablo (0x223a)
- Arctis Nova 7 WoW (0x227a)
- Arctis Nova 7 2 (0x22a1)
- Arctis Nova 7 Gen2 (0x227e)
- Arctis Nova 7 X Gen2 (0x229e)
- Arctis Nova Pro (0x12e0)
- Arctis Nova Pro X (0x12e5)
Also reordered existing entries for better organization.
Note, steelseries [firmware release
103.0.0](https://techblog.steelseries.com/2026/01/21/GG-notes-103.0.0.html)
was a major update for all Nova 7 (Gen 1) Family headsets with new PIDs
being issued for the devices. I only own the Nova 7 which is the only
(previously unknown) PID being added. Additional PIDs will need to be
added for those new identifiers (if any), but this should be basically
every Steelseries Headset which the kernel supports/will eventually
support.
We add some test cases for the previous commits: first (with Claude's
help) we exercise the message creation API internally by passing it
various combinations of incorrect fds with the might_be_truncated flag
set to true or false.
Then we try more of a "real world" test by lowering our fd limit and
sending ourselves a message via the bus and making sure that we
successfully receive a message that has had at least some of its fds
truncated.
sd-bus: allow receiving messages with MSG_CTRUNC set
In the event that we can't receive all of the fds from the message
(which can happen for a number of reasons including LSM denials or
hitting the fd limit of the process) the kernel will set the MSG_CTRUNC
flag. Through our use of recvmsg_safe() we've been treating this as a
fatal error, which will result in dropping the connection.
Let's dial that back a bit: we can receive the message, but when the
user attempts to access the missing fds via sd_bus_message_read_basic()
we can return the (existing) error code of -EBADMSG to indicate that the
fd is missing.
We can do this by using recvmsg() directly, and relaxing some of the
checks on message creation: when (and only when) we have received
MSG_CTRUNC we allow a smaller than expected (per the header) number of
fds to be present. The error check in sd_bus_message_read_basic() was
already there so we don't need to do anything about that.
This puts the receiver of the message into a difficult situation: you
can call sd_bus_message_read_basic() as often as you want but as long as
it keeps returning -EBADMSG it won't progress through the message and
you won't be able to close whatever container you're in. That means
that the user will probably need to abandon processing the message
anyway. So why not just drop the message up front? This approach is
more likely to yield a useful error message, which will be invaluable
for people trying to track down problems caused by LSM denials.
/usr/share/ is a directory commonly accessed by various tools, hence we
really should make sure we umount it lazily (MNT_DETACH), since
otherwise there's a good chance that the umount might simply fail.
conf-files: add flag so that we don't always prefix returned paths with the root dir path used
This is useful in tools such as system-repart where we show the
definition file paths a lot in our output, but if prefixed with the root
path we'd show a temporary mount dir when operating on a image file.
Hence, let's drop the prefix here, and show only the path within the
image.
Mike Yuan [Sat, 24 Jan 2026 17:33:05 +0000 (18:33 +0100)]
sd-event: unpoison memory returned by epoll_pwait2()
Our fuzzer CI recently got bumped to Ubuntu 24.04 with
glibc >= 2.35. Apparently msan is not happy with the new
epoll_pwait2(), hence explicitly mark the memory region
as initialized.
* 6f4d90be5c Do not install autovt@ for upstream builds
* 8cc28a6b82 Install new files for upstream build
* 0d15255073 Use deb-systemd-invoke to reexec instead of manual calls
* db04e5fa0b Use dh_installsystemd to handle journald and networkd
* d8756a4c82 Use dh_installsystemd more to manage units
* 40b23b0d5d d/tests: drop tests-in-lxd
* 5821c5a350 d/control: have systemd-boot depend on efibootmgr for amd64 and arm64 only
units/getty@.service: use [Install]Alias= instead of static alias
In Fedora, kmsconvt@.service is starting to be used instead of getty@.service
to have nicer font handling. This means that we need the autovt@.service alias
point to the new unit. So far the alias was done through a static symlink
because there was little reason to change it. Let's use [Install] instead so
the decision which implementation to use can be made after installation.
Derek J. Clark [Thu, 22 Jan 2026 20:52:03 +0000 (12:52 -0800)]
hwdb: Update Lenovo Legion Go Models
- Different BIOS versions of the Legion Go 2 can init the keyboard
device as set 1 (appears as raw set 2) or as set 2 (appears as
translated set 2). Add the Legion Go 2 to the Translated list.
- While at it, specify the models in a more verbose manner for
posterity.
Signed-off-by: Derek J. Clark <derekjohn.clark@gmail.com>
After the mentioned commit, logind returns an error if the process
already lives in a session, and register_session() short-circuits
without setting systemd.existing flag. Hence systemd.existing
is either false or unset for pam_sm_close_session(), making
the whole logic effectively NOP. Kill it with fire.
Franck Bui [Mon, 19 Jan 2026 17:24:12 +0000 (18:24 +0100)]
pam_systemd: fix regression introduced in v258 by preserving the FIFO fd
Upstream commit 3180c4d introduced a version incompatibility between
pam_systemd.so v258 and logind v257. This is problematic because such version
mismatches can occur in practice: logind still cannot be restarted during a
systemd package upgrade (it's a long-standing limitation, see
https://github.com/systemd/systemd/issues/17308).
When pam_systemd requests a new session, logind v257 returns a FIFO
fd. pam_systemd.so v258 ignores this fd and closes it. logind interprets the
closure as the session leader exiting and immediately terminates the session.
This patch partially reverts commit 3180c4d and restores the handling of the
FIFO fd in pam_systemd. The change is limited to the D-Bus APIs, since the
varlink API was only introduced in logind v258.
os-release: add a new FANCY_NAME= field to /etc/os-release, similar to PRETTY_NAME, that may carry ansi sequences + more unicode chars (#40367)
It's sometimes useful include non-ascii unicode chars in an os name, and
give it some ansi coloring. Since we usualy don't want to show that,
introduce a new field for it, and show it at boot and in thostnamectl
only, with safe fallbacks if colors/emojis are not available.
format-table: add new string cell type that accepts ANSI sequences
For various usecases it's useful that we can embed ANSI sequences in
cells of tables. For example, I hope we can eventually switch "systemctl
status" output to use the table formatter, and multiple of its fields
contain ANSI sequences (since they pack multiple different pieces
information into the same field, and highlight parts of it to
communicate relevance of distinct parts).
Add a distinct cell type for this, which gets special processing when we
output to a terminal that doesn't support ANSI sequences, and to JSON:
we strip the sequences.
Yu Watanabe [Tue, 20 Jan 2026 09:04:33 +0000 (18:04 +0900)]
network/dhcp4: send release message before stopping the client
Otherwise, the socket is already closed and sending release will be
anyway skipped.
With this patch, release message is sent before stopping the client.
```
Jan 20 18:29:41 systemd[1]: Stopping systemd-networkd.service - Network Management...
Jan 20 18:29:41 systemd-networkd[3821255]: wlp59s0: DHCPv4 client: RELEASE
Jan 20 18:29:41 systemd-networkd[3821255]: wlp59s0: DHCPv4 client: STOPPED
Jan 20 18:29:41 systemd-networkd[3821255]: wlp59s0: DHCP lease lost
```
Daan De Meyer [Tue, 2 Dec 2025 10:17:13 +0000 (11:17 +0100)]
portable: Enable unpriv operation
This does not yet support directory images properly
as systemd itself does not support unpriv directory
images properly yet.
The user profiles are a copy of the system profiles but without
DynamicUser=yes (can't be used by user managers) and without
ProtectHome=yes (this masks /home which breaks StateDirectory= which
is lcoated inside /home)
Vunny Sodhi [Wed, 21 Jan 2026 10:27:55 +0000 (12:27 +0200)]
pam_systemd_home: Use PAM_TEXT_INFO for token prompts
The prompts asking the user to physically authenticate
or confirm presence on a security token are informational
requests for action, not error conditions.
This commit changes the message type to PAM_TEXT_INFO,
which is more appropriate for guiding the user through
the authentication process.
shared/fdset: add detailed debug logging to fdset_new_fill()
Currently, when fdset_new_fill() fails to open /proc/self/fd or
encounters an error while processing individual file descriptors
(such as fcntl or fstat failures), it returns a silent error code.
For debugging rarely reproducible failures it becomes difficult to
know the exact cause of failure
This commit updates the function to use log_debug_errno() for all
error paths and hence provides better visibility into why FD collection
failed, including the path of the problematic FD (via fd_get_path)
and its inode type.
Daan De Meyer [Tue, 20 Jan 2026 21:41:40 +0000 (22:41 +0100)]
mountfsd: Add relaxExtensionReleaseChecks
We currently pass this around as a mount option in pid1, which means
privileges are required by mountfsd to mount images that make use of it.
Add an explicit argument for it in varlink instead and remove it client
side from the mount options to remove the need for privileges.
DaanDeMeyer [Tue, 23 Dec 2025 21:08:09 +0000 (22:08 +0100)]
test: Set SYSTEMD_NSS_LOG_LEVEL=info
Currently, our test logs are flooded with useless NSS varlink debug
logs coming from nss-systemd talking to each varlink userdb service
individually. Let's set SYSTEMD_NSS_LOG_LEVEL=info to get rid of these
verbose logs.
DaanDeMeyer [Tue, 23 Dec 2025 21:06:31 +0000 (22:06 +0100)]
nss-util: Add support for $SYSTEMD_NSS_LOG_LEVEL
When setting SYSTEMD_LOG_LEVEL=debug and debugging a tool that happens
to do NSS lookups, the resulting logs from varlink are obnoxiously
verbose. Let's parse a separate log level environment variable in NSS
to allow overriding the log level for NSS specifically so these noisy
logs can be silenced.
Daan De Meyer [Wed, 21 Jan 2026 10:25:36 +0000 (11:25 +0100)]
mkosi: Install libucontext in Arch/Fedora images
Split out of #39771
We don't use make use of libucontext yet but merging this early makes
sure my mkosi cached images don't get invalidated every time I switch
between my other work and the fiber branch.
sysupdate: add simple "freshness" validation to systemd-sysupdate
In order to make "freeze" attacks against the update logic harder let's
add the ability to encode a "Best Before" date into SHA256SUMS directory
listings: if the current time is already beyond that time, we'll ignore
the SHA256SUMS as "stale" and fail the upgrade. Or in other words: the
freeze attack will now result in a client-side error eventually, instead
of success state.
The best before data is encoded in an optional pseudo-file listed in SHA256SUMS:
any file named BEST-BEFORE-YYYY-MM-DD.
Yu Watanabe [Tue, 20 Jan 2026 09:41:11 +0000 (18:41 +0900)]
stat-util: make proc_mounted() not update errno
Typically, proc_mounted() is used in error handling. Hence, it is better
to make it not update the original errno.
Currently, there are two places that returns wrong error code:
- pidref_get_capability() in src/basic/capability-util.c
```c
_cleanup_fclose_ FILE *f = fopen(path, "re");
if (!f) {
if (errno == ENOENT && proc_mounted() == 0)
return -ENOSYS;
return -errno;
}
```
- fdset_new_fill() in src/shared/fdset.c
```c
d = opendir("/proc/self/fd");
if (!d) {
if (errno == ENOENT && proc_mounted() == 0)
return -ENOSYS;
return -errno;
}
```
Rather than fixing them, let's make proc_mounted() not update errno,
otherwise we may make a similar failure in a future.
safforddr [Tue, 13 Jan 2026 18:27:20 +0000 (13:27 -0500)]
tpm2: allow use of recoverable sealing keys
In some use cases it is desirable to use a recoverable (ie duplicatable)
sealing key. Currently objects have the attribute TPMA_OBJECT_FIXEDTPM
and TPMA_OBJECT_FIXEDPARENT hard coded, which will not work with a
recoverable sealing key. This patch sets the object's attributes from
the sealing key's attributes, so that both types of sealing keys will work.
Introduce 'fixate-volume-key' option to repart/cryptsetup to pin the exact LUKS volume key hash (#40343)
Add an option to generate the expected volume key hash for LUKS volumes
by systemd-repart
and put it to crypttab, make systemd-cryptsetup check it upon attaching.
The format of the hash
matches what's currently being measured to TPM2 PCR with
tpm2-measure-pcr=.
sd-varlink: ensure that "any" actually means "any but null"
The new "any" type was implemented by accident that it actually meant
"any but null" – unless marked as "any?" in which case it actually meant
truly any, including null. The spec change in
https://github.com/varlink/varlink.github.io/pull/43 otoh suggested that
"any" really means anything, and "any?" apparently too.
I think the implementation in code makes more sense than the spec change
however, hence let's add some checks/tests to ensure the behaviour of
the code is made explicitly and cared for.
I will prep a spec change to make the spec follow the code on this too.
Nick Rosbrook [Mon, 19 Jan 2026 18:29:52 +0000 (13:29 -0500)]
resolve: include current DNS server in JSON again
The current_dns_server_json object in dns_configuration_json_append() is
always NULL, because the logic to dump the current DNS server to JSON
was removed by mistake in a re-factoring commit. Add that logic back.
Fixes c6b6ac63ea ("resolve: drop unnecessary preparation of empty arrays").