Yu Watanabe [Sat, 3 Jan 2026 03:46:56 +0000 (12:46 +0900)]
core: do not provide non-dynamic user through DBus/Varlink
With a service with DynamicUser= with static user or group, e.g.,
```
$ systemd-run -p DynamicUser=yes -p Group=disk sleep infinity
```
previously the lookup by name and ID through DBus/Varlink are inconsistent:
```
$ busctl call org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager LookupDynamicUserByUID "u" 6
Call failed: Dynamic user ID 6 does not exist.
$ busctl call org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager LookupDynamicUserByName "s" disk
u 6
$ userdbctl group 6
Group name: disk
Disposition: system
GID: 6
Passwords: 1
Service: io.systemd.NameServiceSwitch
$ userdbctl group disk
Group name: disk
Disposition: dynamic
GID: 6
Description: Dynamic Group
Service: io.systemd.DynamicUser
```
With this change, the results of these methods are consistent.
DaanDeMeyer [Fri, 26 Dec 2025 20:58:04 +0000 (21:58 +0100)]
pull-tar: Insist on foreign UID when copying
If we're doing foreign UID range copying, we're going to be joining
a private user namespace before doing the copy. copy_tree() insists
on keeping all UIDs/GIDs the same when copying. Hence, all the
UIDs/GIDs of the files we're copying should be in the private UID
range, which means they need to be owned by the foreign UID range
and we always need to call mountfsd_mount_directory_fd(). So there's
no point in having a fallback path if the source directory is not
foreign UID range owned, we'd simply fail to copy it later. Hence,
insist on the source directory being foreign UID range owned.
Daan De Meyer [Sun, 14 Dec 2025 15:04:57 +0000 (16:04 +0100)]
sd-json: Fix sd_json_variant_type_to_string parameter name
The definition will use i because of the macro, so
let's use i in the declaration as well. We can't
use DECLARE_STRING_TABLE_LOOKUP_TO_STRING() because
sd-json.h is a libsystemd public header.
Daan De Meyer [Wed, 26 Nov 2025 14:52:46 +0000 (15:52 +0100)]
clang-tidy: Block system headers with errors
blkid.h and gmessages.h both use const for arguments that are passed
by value, which is pointless and triggers clang-tidy warnings, so exclude
them from processing.
Daan De Meyer [Mon, 15 Dec 2025 08:08:00 +0000 (09:08 +0100)]
sd-journal: Remove const from function parameter
boot_id is already passed by value, and hence copied.
Since we don't apply const to function parameters
that are copied anywhere else, let's drop the const
here as well for consistency.
Daan De Meyer [Fri, 19 Dec 2025 18:43:21 +0000 (19:43 +0100)]
tree-wide: Use pamh as pam_handle_t parameter name
libpam uses pamh in its function declarations for
the plugin API so let's use the same name in our
tree as well.
Making sure the plugin function definitions match
the plugin function declarations is required to
enable clang-tidy's
readability-inconsistent-declaration-parameter-name
check, but to keep things consistent everywhere we
opt to use pamh tree-wide.
Yu Watanabe [Sat, 25 Oct 2025 04:41:33 +0000 (13:41 +0900)]
libcrypt-util: turn into dlopen() dependency
Note, this drops logging only test case for crypt_preferred_method(),
as that requires explicitly dlopen() the library. But, we should test
that make_salt() and friends automatically dlopen() it.
Yu Watanabe [Sun, 17 Aug 2025 14:03:44 +0000 (23:03 +0900)]
Require libxcrypt-4.4.0 or newer and drop support of libcrypt
libcrypt was no longer built by default since glibc-2.38, and it has been
completely removed since glibc-2.39.
Let's always use libxcrypt, unless when building with musl. As already
major distribution already have libxcrypt-4.4.x, hence let's also bump
the required minimum version to 4.4.0.
libxcrypt cannot be built with musl, hence the previous fallback logic
in libcrypt-util.c are moved to musl/crypt.c.
Note, libxcrypt-4.4.0 was released on 2018-11-20.
See also #38608.
Yu Watanabe [Sun, 17 Aug 2025 15:58:56 +0000 (00:58 +0900)]
Bump required minimum version of libseccomp to 2.4.0
Major distributions already have libseccomp 2.5.x or newer.
Let's bump to the required minimum version to 2.4.0, which provides
SCMP_ACT_KILL_PROCESS, SCMP_ACT_LOG, SCMP_ARCH_PARISC, and
SCMP_ARCH_PARISC64.
Note, libseccomp 2.4.0 was released on 2019-03-15.
Yu Watanabe [Fri, 2 Jan 2026 00:25:43 +0000 (09:25 +0900)]
network: Support interface-bound ECMP routes in MultiPathRoute= (#39742)
MultiPathRoute= can now specify device-only nexthops without a gateway
address, e.g. MultiPathRoute=@wg0. This enables ECMP configurations over
interfaces that don't use gateway addresses, such as WireGuard tunnels.
The syntax is extended from "address[@device] [weight]" to
"[address]@device [weight]". The address is now optional, but at least
one of gateway or device must be specified. The @ symbol must still be
present for device-only routes, making the syntax unambiguous: @wg0
specifies a device, while a bare IP address specifies a gateway.
Device-only nexthops are only available for IPv4 routes. Device-only
multipath routes for IPv6 are not supported by the kernel's netlink
interface and will be rejected with a warning.
This change is fully backwards compatible. All existing configurations
continue to work unchanged, as they always included a gateway address.
Daan De Meyer [Mon, 22 Dec 2025 14:11:18 +0000 (15:11 +0100)]
vmspawn: Add --user/--system and support user session machined registration
The UX of registering with the user session machined
instance is much better as there won't be an authorization
prompt. To make that available for users, let's add --user
and --system switches for vmspawn. For backwards compat, we'll
still try to register with the system machined instance if the
user machined instance is not available.
DaanDeMeyer [Thu, 25 Dec 2025 18:24:17 +0000 (19:24 +0100)]
openssl-util: Make ret_user_interface required output argument
To avoid the argument accidentally not getting passed anymore during
refactoring, let's make it a required output argument so that callers
are required to provide it.
This was originally introduced to resolve deadlock caused by
dbus broker calling into nss-systemd which in turn goes via
dbus for user lookup. This is now handled differently and
the interface has been sitting unused for half a decade now.
Kill it.
Daan De Meyer [Fri, 12 Dec 2025 16:06:38 +0000 (17:06 +0100)]
string-table: Introduce DECLARE_STRING_TABLE_LOOKUP() and friends
Let's introduce these for the following two reasons:
- Using them makes sure the parameter names match between declaration
and definition (if both use the corresponding macros).
- They make sure developers can't forget the _const_ and _pure_
attributes for the declarations.
This commit also includes some include sorting fixes
quirks: Re-add D330 accel_matrix as identity one (#40226)
When testing to correct accelerometer values I set locally the identity
matrix to override the quirk. The values were fine but removing all the
matrices give incorrect values.
The mistake was thinking that identity matrix is the default one when no
quirks are set. It is, but only when the ACPI doesn't have another one.
Set identity matrix for this device to correct accelerometer values.
tuhaowen [Wed, 31 Dec 2025 02:46:30 +0000 (10:46 +0800)]
udev/scsi_id: increase MAX_SERIAL_LEN from 256 to 512
The current MAX_SERIAL_LEN value of 256 is insufficient for some SCSI
devices with non-standard serial number lengths. In do_scsi_page80_inquiry(),
the required buffer length is calculated as:
where buf[3] contains the serial number length reported by the device.
According to the SCSI specification, this field is an unsigned 8-bit
value, meaning it can theoretically be up to 255 bytes. This results
in a maximum required length of 280 bytes, exceeding the current limit
of 256 bytes.
When this occurs, scsi_id fails with an error message like:
"length 256 too short - need 280"
This has been observed with certain vendor devices that report unusually
long serial numbers in VPD page 0x80.
Increase MAX_SERIAL_LEN to 512 to accommodate the maximum possible
serial number length plus all required prefixes (vendor, model, and
type identifiers), providing sufficient headroom for non-compliant
devices while maintaining reasonable memory usage.
Guiorgy [Wed, 31 Dec 2025 14:58:58 +0000 (18:58 +0400)]
Support Bash completions for short option group in journalctl (#40214)
Currently, the Bash completions for journalctl tries to match the
previous word _**exactly**_, which leads to the following issue:
`journalctl -u dock` correctly auto completes to `journalctl -u
docker.service`, but `journalctl -eu` provides no completions at all,
which is a shame since I never use the `-u` option alone (almost always
`-eu` or `-efu`, I wish the `-e` option was the default but I digress).
The proposed solution is to assume words that start with only a single
dash and consist of only letters are short option groups and handle them
as if the previous word was the short option using the last character,
e.g. `-efu` -> `-u`.
The commit added serialization, but deserialization wasn't in place.
Follow the usual practice of pinning the bpf link fd until we install
the new instance.
* e3642f81d3 kmod: Only use --modname if available
* ddea81d81e arch: Download archlinux-keyring with pacman
* 4a44e1831b Remove unneeded lambdas
* 9c3d23757c Configure pyright included files
* 5e037d514c qemu: Register with systemd-machined in user session
* c4c3d793d0 Create package cache dir before invoking pacman
* d53761c4dd distribution: do not default to release=VERSION_ID for openSUSE Tumbleweed
* c5bc9138fc Wrap build_microcode_initrd in complete_step
* 635159975d Fix typo in manpage
* 59f5f0741e mkosi-addon: drop Output=addon, addon.py already has a default
* be85b8ca0b sandbox: return raw error code from the kernel and friends on failure
* 56f25c1a41 config: replace deprecated sandbox verb with box in help message
* ae24c527d7 sandbox: fix wrong errno passed to OSError()
* e7b9612760 verity: do not copy signing cert in addons/portables/extensions
* f3a029b736 Bump version to 27~devel
* 84af20892b Release 26
* 3fcd3a0fde Adjust logging messages for kmod/fw resolution
* d44aae12b4 Revert "Do not try to install packages that are listed in RemovePackages="
* 1873ad0184 portable: Make sure mountpoints exist in the image
* 5dc693feb0 initrd: Inherit keymap, timezone, hostname and rootpw by default
There are multiple ways to encode ANSI ST, and we generally prefer ESC \
for it, for reasons explained in terminal-util.h. Hence, let's actually
follow this rule in the terminal reset logic, and use the ANSI_ST macro.
This will change the byte sequence generated (as it means we use ESC \
rather than BEL), but it doesn't change behaviour, as the two sequences
should be equivalent.
terminal_reset_ansi_req() would try to put terminal in nonblocking
mode temporarily again, hence just avoid the back and forth
and reset nonblocking as last step.
Luca Boccassi [Thu, 18 Dec 2025 17:18:11 +0000 (17:18 +0000)]
test: fix (again) race condition in TEST-80-NOTIFYACCESS
Even with the previous fix, it can still happen that pid1
sends SIGHUP to the script after 'sdnotify --ready' but before
'wait', so the test can still get stuck:
[ 2444.373448] reload-timeout.sh[158]: + set -o pipefail
[ 2444.373502] reload-timeout.sh[158]: + COUNTER=0
[ 2444.373590] reload-timeout.sh[158]: + trap sighup_handler SIGHUP
[ 2444.373639] reload-timeout.sh[158]: + export SYSTEMD_LOG_LEVEL=debug
[ 2444.373670] reload-timeout.sh[158]: + SYSTEMD_LOG_LEVEL=debug
[ 2444.373790] reload-timeout.sh[158]: + wait_for_signal 1
[ 2444.373871] reload-timeout.sh[158]: + local notify=1
[ 2444.373912] reload-timeout.sh[158]: + local p
[ 2444.374079] reload-timeout.sh[158]: + p=159
[ 2444.374123] reload-timeout.sh[159]: + sleep infinity
[ 2444.375358] systemd[1]: reload-timeout.service: Got notification message from PID 158: READY=1
[ 2444.375363] systemd[1]: reload-timeout.service: Changed start -> running
[ 2444.375368] systemd[1]: reload-timeout.service: Job 294 reload-timeout.service/start finished, result=done
[ 2444.375374] systemd[1]: Started reload-timeout.service.
[ 2444.375766] systemd[1]: reload-timeout.service: Failed to send unit change signal for reload-timeout.service: Connection reset by peer
[ 2444.376464] reload-timeout.sh[158]: + '[' 1 -eq 1 ']'
[ 2444.376464] reload-timeout.sh[158]: + systemd-notify --ready
[ 2444.376518] TEST-80-NOTIFYACCESS.sh[157]: Job for reload-timeout.service finished.
[ 2444.376518] TEST-80-NOTIFYACCESS.sh[157]: Got result done/Success for job reload-timeout.service.
[ 2444.376518] TEST-80-NOTIFYACCESS.sh[157]: Bus n/a: changing state RUNNING → CLOSED
[ 2444.376952] TEST-80-NOTIFYACCESS.sh[92]: + systemctl reload --no-block reload-timeout.service
[ 2444.379548] TEST-80-NOTIFYACCESS.sh[161]: Bus n/a: changing state UNSET → OPENING
[ 2444.379548] TEST-80-NOTIFYACCESS.sh[161]: sd-bus: starting bus by connecting to /run/systemd/private...
[ 2444.379548] TEST-80-NOTIFYACCESS.sh[161]: Bus n/a: changing state OPENING → AUTHENTICATING
[ 2444.379548] TEST-80-NOTIFYACCESS.sh[161]: Executing dbus call org.freedesktop.systemd1.Manager ReloadUnit(reload-timeout.service, replace)
[ 2444.379548] TEST-80-NOTIFYACCESS.sh[161]: Bus n/a: changing state AUTHENTICATING → RUNNING
[ 2444.379910] systemd-notify[160]: Notify message sent to '/run/systemd/notify': "READY=1"
[ 2444.379931] systemd-notify[160]: Notify message sent to '/run/systemd/notify': "BARRIER=1"
[ 2444.382218] systemd[1]: reload-timeout.service: Trying to enqueue job reload-timeout.service/reload/replace
[ 2444.382241] systemd[1]: reload-timeout.service: Installed new job reload-timeout.service/reload as 366
[ 2444.382248] systemd[1]: reload-timeout.service: Enqueued job reload-timeout.service/reload as 366
[ 2444.383905] systemd[1]: reload-timeout.service: Service has no extensions to reload.
[ 2444.384925] systemd[1]: reload-timeout.service: Changed running -> reload-signal
[ 2444.384935] systemd[1]: Reloading reload-timeout.service...
[ 2444.386410] reload-timeout.sh[158]: ++ sighup_handler
[ 2444.386410] reload-timeout.sh[158]: ++ echo hup1
[ 2444.386455] TEST-80-NOTIFYACCESS.sh[161]: Bus n/a: changing state RUNNING → CLOSED
[ 2444.386555] TEST-80-NOTIFYACCESS.sh[92]: + timeout 10 bash -c 'until [[ $(systemctl show reload-timeout.service -P SubState) == "reload-signal" ]]; do sleep .5; done'
[ 2444.395566] TEST-80-NOTIFYACCESS.sh[165]: Bus n/a: changing state UNSET → OPENING
[ 2444.395566] TEST-80-NOTIFYACCESS.sh[165]: sd-bus: starting bus by connecting to /run/systemd/private...
[ 2444.396041] TEST-80-NOTIFYACCESS.sh[165]: Bus n/a: changing state OPENING → AUTHENTICATING
[ 2444.396041] TEST-80-NOTIFYACCESS.sh[165]: Showing one /org/freedesktop/systemd1/unit/reload_2dtimeout_2eservice
[ 2444.401911] TEST-80-NOTIFYACCESS.sh[165]: Bus n/a: changing state AUTHENTICATING → RUNNING
[ 2444.401911] TEST-80-NOTIFYACCESS.sh[165]: Bus n/a: changing state RUNNING → CLOSED
[ 2444.403806] TEST-80-NOTIFYACCESS.sh[92]: + sync_in hup1
[ 2444.403806] TEST-80-NOTIFYACCESS.sh[92]: + read -r x
[ 2444.403964] reload-timeout.sh[158]: + wait 159
[ 2444.403988] TEST-80-NOTIFYACCESS.sh[92]: + test hup1 = hup1
[ 2444.403988] TEST-80-NOTIFYACCESS.sh[92]: + timeout 10 bash -c 'until [[ $(systemctl show reload-timeout.service -P SubState) == "reload-notify" ]]; do sleep .5; done'
Try to check if the signal handler has ran by checking the counter,
and avoid waiting and immediately return if it has changed
Daan De Meyer [Sat, 20 Dec 2025 21:10:02 +0000 (22:10 +0100)]
Follow ups for #39806
We drop the optimization for verify_sigchld as the
check differs based on the options passed and the
extra syscalls are certainly not going to matter
compared to the cost of forking a child process.
This adds 11 commits with minor preparatory commits for PR #39621. That
PR has tests that cover all this, even if this one doesn't, but the bits
added here are relatively minor.