]> git.ipfire.org Git - thirdparty/systemd.git/log
thirdparty/systemd.git
35 hours agorun: reject waiting for remain-after-exit services 43003/head
dongshengyuan [Mon, 13 Jul 2026 06:23:26 +0000 (14:23 +0800)] 
run: reject waiting for remain-after-exit services

Reproducer:
  unit=run-wait-rae-$(date +%s)
  sudo timeout 3s systemd-run --wait --remain-after-exit \
      --unit="$unit" /bin/true
  echo $?
  systemctl is-active "$unit.service"

Before, the command timed out with exit status 124 while the service
stayed active. --wait waits for deactivation, but RemainAfterExit=yes
keeps the service active after the command exits.

Follow-up for 2a453c2ee3090e1942bfd962262f3eff0adbfa97

35 hours agorun: reject JSON output with verbose logs
dongshengyuan [Mon, 13 Jul 2026 06:21:02 +0000 (14:21 +0800)] 
run: reject JSON output with verbose logs

Reproducer:
  sudo systemd-run --wait --verbose --json=short /bin/echo hi

Before, systemd-run printed JSON metadata to stdout while --verbose
also spawned journalctl output on stdout. The resulting stream mixed JSON
with journal lines, so reject the conflicting options.

Follow-up for 744ca8f616b98f579d930176f6262e1ac197840b

35 hours agorun: reject JSON output in scope mode
dongshengyuan [Mon, 13 Jul 2026 06:18:42 +0000 (14:18 +0800)] 
run: reject JSON output in scope mode

Reproducer:
  sudo systemd-run --scope --json=short /bin/echo hi

Before, systemd-run printed JSON metadata to stdout and then executed
the scope command on the same stdout. The combined stream was not valid
JSON, so reject --json= in scope mode.

Follow-up for fe5a6c47af675bc0020c545d86fb103492e1d77c

35 hours agorun: reject JSON output for trigger units
dongshengyuan [Mon, 13 Jul 2026 06:16:55 +0000 (14:16 +0800)] 
run: reject JSON output for trigger units

Reproducer:
  unit=run-json-trigger-$(date +%s)
  sudo systemd-run --json=short --unit="$unit" \
      --on-active=30s \
      /bin/true

Before, trigger mode accepted --json=short but printed only human-readable
"Running timer as unit" and "Will run service" lines. Reject the option
until trigger mode has structured output.

Follow-up for fe5a6c47af675bc0020c545d86fb103492e1d77c

35 hours agorun: reject JSON output with stdio forwarding
dongshengyuan [Mon, 13 Jul 2026 06:14:33 +0000 (14:14 +0800)] 
run: reject JSON output with stdio forwarding

Reproducer:
  sudo systemd-run --wait --pipe --json=short /bin/echo hi

Before, systemd-run wrote its JSON metadata to stdout and then passed
the command stdout through the same stream. The combined output was not
valid machine-readable JSON, so reject the conflicting modes.

Follow-up for fe5a6c47af675bc0020c545d86fb103492e1d77c

35 hours agorun: reset groups before scope uid switch
dongshengyuan [Mon, 13 Jul 2026 06:12:30 +0000 (14:12 +0800)] 
run: reset groups before scope uid switch

Reproducer:
  sudo systemd-run --scope --uid=nobody /usr/bin/id

Before, the command ran as nobody but kept the caller supplementary
root group, for example groups=65534(nogroup),0(root). Scope mode
performs the uid/gid switch locally, so initialize the target user groups
before dropping privileges.

Follow-up for 4de33e7f3238a6fe616e61139ab87e221572e5e5

35 hours agorun: accept explicit trigger unit names
dongshengyuan [Mon, 13 Jul 2026 06:05:52 +0000 (14:05 +0800)] 
run: accept explicit trigger unit names

Reproducer:
  unit=run-explicit-path-$(date +%s)
  systemd-run --unit="$unit.path" \
      --path-property=PathExists=/tmp \
      /bin/true
  echo $?

Before, an explicit .path unit name was not recognized as the
trigger unit. It was mangled again as a service name, so PID 1 rejected
the transient request with an already-loaded unit conflict.

Follow-up for d59ef3e24362aa7a9e209ed07db5feca1a2cdb8e

35 hours agorun: reject --ignore-failure in scope mode
dongshengyuan [Mon, 13 Jul 2026 05:56:52 +0000 (13:56 +0800)] 
run: reject --ignore-failure in scope mode

Reproducer:
  sudo systemd-run --scope --ignore-failure /bin/false
  echo $?

Before, the option was accepted but had no effect because scope mode
executes the command locally after creating the scope. The flag is only
encoded into service ExecStart properties, so accept it only where it can
be applied.

Follow-up for 1072d9473123ed174e033704fc5222216b655c9e

35 hours agorun: honor --no-block for trigger units
dongshengyuan [Mon, 13 Jul 2026 05:54:14 +0000 (13:54 +0800)] 
run: honor --no-block for trigger units

Reproducer:
  unit=run-nb-trigger-$(date +%s)
  systemd-run --no-block --collect --unit="$unit" \
      --socket-property=ListenStream=/proc/systemd-run-repro/socket \
      /usr/bin/true
  echo $?

Before, systemd-run still waited for the trigger unit job and
propagated the socket start failure. With --no-block it should only
verify and enqueue the request, as the service path already does.

Follow-up for 3d161f991e16369aa59f447eb4cdb90af33261c8

39 hours agouserdb: suppress userdb queries for backends indicating uid/gid/name range info via...
Luca Boccassi [Mon, 13 Jul 2026 23:19:32 +0000 (00:19 +0100)] 
userdb: suppress userdb queries for backends indicating uid/gid/name range info via xattrs on entrypoint sockets (#42961)

Let's optimize userdb queries a bit: by encoding the covered UID/GID
ranges and user/group name patterns on the varlink entrypoint sockets
for userdb backends we can make them wake up less and reduce the work
triggered by queries.

45 hours agosysupdate: add "suggestion" concept to feature and component enablement (#42970)
Luca Boccassi [Mon, 13 Jul 2026 18:07:50 +0000 (19:07 +0100)] 
sysupdate: add "suggestion" concept to feature and component enablement (#42970)

46 hours agorepart: allow empty EncryptedVolume= volume name (#42889)
Lennart Poettering [Mon, 13 Jul 2026 16:47:09 +0000 (18:47 +0200)] 
repart: allow empty EncryptedVolume= volume name (#42889)

Treat an empty volume name alongside other fields as unset instead of
rejecting it as invalid.

Example use case:
```
EncryptedVolume=:none:discard
```

In this case, the volume name is not specified so it can be generated as
luks-UUID.

From the docs:

> EncryptedVolume=
> Specifies how the encrypted partition should be set up. Takes at least
one and at most four fields separated with a colon (":"). The first
field specifies the encrypted volume name under /dev/mapper/. If not
specified, "luks-UUID" will be used where "UUID" is the LUKS UUID.

47 hours agoprocess-util: introduce prctl_safe() and port everything over to it (#43006)
Luca Boccassi [Mon, 13 Jul 2026 16:02:57 +0000 (17:02 +0100)] 
process-util: introduce prctl_safe() and port everything over to it (#43006)

prctl() is an API full of pitfalls: it is variadic, and some interfaces
don't expect zero-initialization of excess arguments, and others do.
Moreover, the parameters are "long", and nonetheless we usually pass
"int" to them. If we are too dumb to call it properly, let's just not
call it directly anymore, but let's add a wrapper around it that makes
the function non-variadic and declares the right types. Then, let's port
over everything to it.

This is inspired by #42996, but we had issues with this many times,
before and looking at this PR one can see that we otherwise still are
having the issue at numerous other places.

47 hours agocryptsetup: add Argon2id-based PIN mode for TPM2 enrollment (#41859)
Lennart Poettering [Mon, 13 Jul 2026 15:55:47 +0000 (17:55 +0200)] 
cryptsetup: add Argon2id-based PIN mode for TPM2 enrollment (#41859)

The current TPM2 PIN mode is flawed as a compromised TPM directly
exposes
the sealed secret which is the LUKS volume key itself
(https://github.com/systemd/systemd/pull/27502 and
https://github.com/systemd/systemd/issues/37386).

Goal: add Argon2id-based PIN hardening to TPM2 enrollment, making
the TPM a second factor rather than a single point of failure:

1. Password + salt → Argon2id → 512-bit key split into Key1 + Key2
2. Key2 (base64-encoded) is used as the PIN to seal a random secret
in the TPM
3. Key1 + unsealed secret → HKDF-SHA256 → final LUKS volume key

This implementation ensures that if the TPM is compromised, an attacker
still needs the password to derive Key1 and combine it with the unsealed
secret.

The --tpm2-with-pin= option now accepts three values:
- false (no PIN used)
- true (PIN hardened with Argon2id - default)
- "direct" (legacy PIN without Argon2id for backward compatibility)

Argon2id parameters are customizable via:

--tpm2-argon2id-memory=
--tpm2-argon2id-iterations=
--tpm2-argon2id-parallelism=
--tpm2-argon2id-iter-time=

These default to a function of available CPUs and physical memory, with
a benchmark that scales iterations to the target time (default: 2s) and
falls back to ARGON2ID_PARAMETERS_DEFAULT (64 MiB, 8 iter, 4 lanes) when
auto detection fails.
Also if the runtime OpenSSL lacks Argon2id support (< 3.2), the feature
silently falls back to direct PIN mode with a warning.

Added includes:
- src/cryptenroll/cryptenroll.c: cpu-set-util.h, limits-util.h,
time-util.h
for Argon2id benchmark auto-tuning (cpus_online, physical_memory_scale,
  now/usec_t)
- src/cryptenroll/cryptenroll-tpm2.c: crypto-util.h for
Argon2IdParameters
  struct in load_volume_key_tpm2()
- src/shared/tpm2-util.h: crypto-util.h for Argon2IdParameters in
  tpm2_make_luks2_json() API
- src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c: crypto-util.h for
  kdf_argon2id_derive()/kdf_hkdf_sha256() on the token unlock path

47 hours agosysupdate: add support for --component-all + --feature-all + --feature-suggested... 42970/head
Lennart Poettering [Tue, 30 Jun 2026 19:46:46 +0000 (21:46 +0200)] 
sysupdate: add support for --component-all + --feature-all + --feature-suggested to enable-feature verb

This adds similar concepts as we already have for enable-component:
let's add a way to enable all features or the suggeste dones, and
possibly on all components.

Or in other words, with this:

  systemd-sysupdate enable-component -S
  systemd-sysupdate enable-feature -A -s

We'll automatically enable all suggested components, and all features of
them.

47 hours agosysupdate: validate feature name syntax before using it
Lennart Poettering [Tue, 30 Jun 2026 19:46:07 +0000 (21:46 +0200)] 
sysupdate: validate feature name syntax before using it

Let's tighten the rules on features, and enforce a sensible naming
policy.

47 hours agosysupdate: add feature select
Lennart Poettering [Wed, 24 Jun 2026 15:55:01 +0000 (17:55 +0200)] 
sysupdate: add feature select

Prepartion for the next commit: also allow selecting the all or
suggested features.

47 hours agosysupdate: implement --component-all and --component-suggested for enable-component...
Lennart Poettering [Wed, 24 Jun 2026 15:54:26 +0000 (17:54 +0200)] 
sysupdate: implement --component-all and --component-suggested for enable-component and disable-component

Let's now introduce "systemd-sysupdate enable-component
--component-suggested" and systemd-sysupdate enable-component
--component-all" for enabling all or all suggested components at once.
Similar, if used for disable-component will disable all components or
those not suggested.

47 hours agosysupdate: introduce --component-suggested similar to --component-all
Lennart Poettering [Wed, 24 Jun 2026 15:25:18 +0000 (17:25 +0200)] 
sysupdate: introduce --component-suggested similar to --component-all

While --component-all really picks all components --component-suggested
picks only the suggested ones.

Note that none of the verbs currently implement the concept, they will
all refuse the option. Hooking this up is going to be added next.

47 hours agosysupdate: add a "suggests" concept to features and components
Lennart Poettering [Wed, 24 Jun 2026 15:09:19 +0000 (17:09 +0200)] 
sysupdate: add a "suggests" concept to features and components

Let's make it possible to "suggest" that certain features or components
are enabled under some conditions.

For this, both features and components gain two things:

1. A Suggested= field which takes a boolean. If true the
   feature/component will be suggested for installation, if false it
   will not.

2. A set of SuggestedOnXYZ= settings are modelled after ConditionXYZ= in
   unit files (and implement a subset of them), will suggest some
   component/feature under specific conditions.

The result of the condition is shown in the various output tools.

47 hours agotimer: avoid re-arming WakeSystem=yes timer after suspend
Frantisek Sumsal [Thu, 9 Jul 2026 10:37:06 +0000 (12:37 +0200)] 
timer: avoid re-arming WakeSystem=yes timer after suspend

There's an edge case where a single-shot timer using WakeSystem=yes
could get re-armed after elapsing. For example, when a timer is created
using:

$ systemd-run --user --on-active="1m" --timer-property=WakeSystem=yes flatpak run io.bassi.Amberol

and the system is then suspended, following sequence of events may
happen:

Jul 08 06:57:25 systemd[2640]: run-p192456-i199160.timer: Installed new job run-p192456-i199160.timer/start as 7675
Jul 08 06:57:25 systemd[2640]: run-p192456-i199160.timer: Enqueued job run-p192456-i199160.timer/start as 7675
Jul 08 06:57:25 systemd[2640]: run-p192456-i199160.timer: Monotonic timer elapses in 59.999999s.
Jul 08 06:57:25 systemd[2640]: run-p192456-i199160.timer: Changed dead -> waiting
Jul 08 06:57:25 systemd[2640]: run-p192456-i199160.timer: Job 7675 run-p192456-i199160.timer/start finished, result=done
Jul 08 06:57:25 systemd[2640]: Started [systemd-run] /usr/bin/flatpak run io.bassi.Amberol.
Jul 08 06:58:13 systemd[2640]: run-p192456-i199160.timer: Time change, recalculating next elapse.
Jul 08 06:58:13 systemd[2640]: run-p192456-i199160.timer: Monotonic timer elapses in 12.785674s.
Jul 08 06:58:26 systemd[2640]: run-p192456-i199160.timer: Timer elapsed.
Jul 08 06:58:26 systemd[2640]: run-p192456-i199160.timer: Changed waiting -> running
Jul 08 06:58:29 systemd[2640]: run-p192456-i199160.timer: Got notified about unit deactivation.
Jul 08 06:58:29 systemd[2640]: run-p192456-i199160.timer: Monotonic timer elapses in 33.544681s.
Jul 08 06:58:29 systemd[2640]: run-p192456-i199160.timer: Changed running -> waiting
Jul 08 06:59:48 systemd[2640]: run-p192456-i199160.timer: Timer elapsed.

1) The timer is armed at 06:57:25. timer_enter_waiting()
   calculates following values:

   base = M0 (current CLOCK_MONOTONIC)
   usec_shift_clock(base, CLOCK_MONOTONIC, CLOCK_BOOTTIME_ALARM) = M0 (no delta yet)
   v->next_elapse = M0 + 60s

   The timer is on CLOCK_BOOTTIME_ALARM at M0 + 60s

2) System suspends. If the system ran for ~12s and was suspended for
   ~36s, at resume we'd get:

   CLOCK_MONOTONIC = M0 + 12s
   CLOCK_BOOTTIME = M0 + 12s + 36s = M0 + 48s

3) timer_time_change() fires and calls timer_enter_waiting(t, true)

   Because time_change=true, v->next_elapse is not recalculated and
   keeps the original M0 + 60s value. The timer then correctly computes
   the remaining time as ~12.8 seconds:

        Jul 08 06:58:13 ...: Monotonic timer elapses in 12.785674s.

4) Timer elapses at 06:58:26

        Jul 08 06:58:26 ...: Timer elapsed.

   timer_enter_running() sets last_trigger.monotonic to CLOCK_MONOTONIC
   (which equals to M0 + 12s before suspend + 13s after suspend, thus
   + 25s)

5) Unit deactivates at 06:58:29

   timer_trigger_notify() calls timer_enter_waiting(t, false) -
   time_change=false; that means that this time v->next_elapse gets
   recalculated:

   base = inactive_exit_timestamp.monotonic = M0 (i.e. when the timer was originally armed)
   usec_shift_clock(M0, CLOCK_MONOTONIC, CLOCK_BOOTTIME_ALARM)
        a = now(CLOCK_MONOTONIC) = M0 + 28s
        b = now(CLOCK_BOOTTIME_ALARM) = M0 + 64s
        result = b - (a - M0) = (M0 + 64s) - 28s = M0 + 36s => the time spent in suspend

   Hence v->next_elapse = (M0 + 36s) + 60s = M0 + 96s

   This then skips disabling of one-shot timers in the following check,
   because the expression

        v->next_elapse < triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t))

   is false, because the v->next_elapse (M0 + 96s) is not less than the
   current time (M0 + 64s), so the timer is re-armed again:

        Jul 08 06:58:29 ...: Monotonic timer elapses in 33.544681s

Let's mitigate this by skipping the next elapse timestamp recalculations
for one-shot timers for which we've already calculated the value in this
activation cycle.

Resolves: #42929

2 days agotree-wide: port to prctl_safe() 43006/head
Lennart Poettering [Mon, 13 Jul 2026 08:12:46 +0000 (10:12 +0200)] 
tree-wide: port to prctl_safe()

2 days agonsresource: port from PR_GET_NAME to pid_get_comm()
Lennart Poettering [Mon, 13 Jul 2026 08:42:28 +0000 (10:42 +0200)] 
nsresource: port from PR_GET_NAME to pid_get_comm()

SImilar reasons as for the memfd change: let's normalize behaviour and
always use pid_get_comm().

This adds escaping here for the first time, which is a good thing.

2 days agomemfd-util: port to pid_get_comm()
Lennart Poettering [Mon, 13 Jul 2026 08:18:04 +0000 (10:18 +0200)] 
memfd-util: port to pid_get_comm()

Let's the common function for querying the local thread name.

This changes the escaping rules when the therad name is not quite
kosher: previously we'd just escape invalid UTF-8 charcaters, now we do
what we usually do: also escape control characters and such, and limit
us to ASCII.

The description generated here is mostly for debug purposes, and process
names should normally not require this escaping anyway (it's mostly
paranoia), hence I think this change in behaviour should be fine, it's
not part of the API in any form.

2 days agoprocess-util: introduce proc_get_timerslack()
Lennart Poettering [Mon, 13 Jul 2026 09:20:03 +0000 (11:20 +0200)] 
process-util: introduce proc_get_timerslack()

2 days agoprocess-util: introduce trivial proc_set_nnp() helper
Lennart Poettering [Mon, 13 Jul 2026 08:48:05 +0000 (10:48 +0200)] 
process-util: introduce trivial proc_set_nnp() helper

2 days agoprocess-util: introduce proc_set_comm() helper
Lennart Poettering [Mon, 13 Jul 2026 08:32:41 +0000 (10:32 +0200)] 
process-util: introduce proc_set_comm() helper

This operation is done at a bunch of places, let's add a type-safe
helper for it.

2 days agoprocess-util: introduce prctl_safe()
Lennart Poettering [Mon, 13 Jul 2026 08:12:07 +0000 (10:12 +0200)] 
process-util: introduce prctl_safe()

2 days agoudev: fix several option parsing edge cases (#42997)
Luca Boccassi [Mon, 13 Jul 2026 12:42:27 +0000 (13:42 +0100)] 
udev: fix several option parsing edge cases (#42997)

Boundary tests were conducted on the udev subsystem, and some issues
were identified and resolved.

2 days agorepart: Some fixes for --copy-from= (#42976)
Luca Boccassi [Mon, 13 Jul 2026 12:33:24 +0000 (13:33 +0100)] 
repart: Some fixes for --copy-from= (#42976)

A bunch of things I noticed that aren't correct about `--copy-from` and
grain sizes + paddings.

2 days agosd-varlink: async upgrade support (#42974)
Lennart Poettering [Mon, 13 Jul 2026 12:29:06 +0000 (14:29 +0200)] 
sd-varlink: async upgrade support (#42974)

With 2c6f9af8e5425c2086fbc8ca496843f162e4af9b sd-varlink gained protocol
upgrade support, however only in a synchronous fashion. This adds
asynchronous protocol upgrade for the server side, thus enabling
multiplexing daemons (i.e. those that handle multiple connections from
the same event loop) to support protocol upgrades too.

I plan to use this in the upcoming "ptybroker" component that allows
acquiring a pty through varlink.

/cc @mvo5

2 days agorepart: Don't copy trailing padding when using --copy-from= 42976/head
Jonas Dreßler [Thu, 9 Jul 2026 13:22:13 +0000 (15:22 +0200)] 
repart: Don't copy trailing padding when using --copy-from=

Currently, --copy-from= copies the paddings in between the source partitions,
as well as the trailing padding that is at the end of the source partition table.
It doesn't copy the leading padding at the start of the source partition table
though.

This seems inconsistent, and likely it was an oversight that the trailing padding
is copied.

Fix that, and add a test to ensure we don't regress.

2 days agorepart: Clarify and test that --copy-from= argument respects grain size
Jonas Dreßler [Tue, 7 Jul 2026 11:15:36 +0000 (13:15 +0200)] 
repart: Clarify and test that --copy-from= argument respects grain size

The --copy-from= argument currently is documented as "copied partitions will have
the same size". This doesn't hold true in the case where a different grain-size is
passed to repart. Because `partition_min/max_size()` currently do rounding, the
size is implicitly rounded to grain size, and therefore partitions are enlarged
to align to grain size whenever possible.

Clarify this behavior and change the manpage, and also add a test for it.

2 days agorepart: Don't get old grain size from fdisk for --copy-from=
Jonas Dreßler [Tue, 7 Jul 2026 12:41:16 +0000 (14:41 +0200)] 
repart: Don't get old grain size from fdisk for --copy-from=

This is a little bit confusing, but grain size is not actually stored in the gpt
metadata. Rather, fdisk's `get_grain_size()` returns an autodiscovered "optimal io
size" value as grain size. This might not actually be the grain size that the
disk we're copying is using.

Since we're setting the padding of the copied partitions using that value from
fdisk, we're rounding the new paddings by fdisk's optimal grain size, which is
usually 1MiB (a lot more then the default 4KiB that we're using otherwise).

Set the grain size here to 1 byte instead, ensuring that the min/max padding set
is exactly the padding that was present before.

Also add a test to confirm the behavior is fixed: The test calls --copy-from= on
an existing disk with 4MiB grain size, and because we pass --grain-size=512, now
no rounding should happen and the paddings should be transferred to exactly the
same size.

2 days agonresourced: add user.userbd.* xattrs to nsresourced userdb socket 42961/head
Lennart Poettering [Fri, 10 Jul 2026 07:13:34 +0000 (09:13 +0200)] 
nresourced: add user.userbd.* xattrs to nsresourced userdb socket

2 days agoudevadm-trigger: reject invalid wait-daemon timeout 42997/head
dongshengyuan [Mon, 13 Jul 2026 02:53:48 +0000 (10:53 +0800)] 
udevadm-trigger: reject invalid wait-daemon timeout

Return from argument parsing when --wait-daemon= cannot be parsed.

This matches the other timeout options.

Reproducer:
  udevadm trigger --dry-run --wait-daemon=bad

Before:
  Failed to parse timeout value 'bad', ignoring: Invalid argument

Follow-up:
  2001622c58c1989f386086d11bd2a00d5fe00a30

2 days agoudev-config: merge configured children max
dongshengyuan [Mon, 13 Jul 2026 02:46:55 +0000 (10:46 +0800)] 
udev-config: merge configured children max

Merge children_max from the per-source UdevConfig values before
defaulting it from system resources.

Reproducer:
  systemd-udevd --debug --children-max=1

Before:
  Set children_max to 32

Follow-up:
  04fa5c1580ad388af3477ecfd7d4aa7d7f5cee30

2 days agoman/udevadm: update device-id-of-file arguments
dongshengyuan [Mon, 13 Jul 2026 02:41:03 +0000 (10:41 +0800)] 
man/udevadm: update device-id-of-file arguments

udevadm info rejects positional devices together with
--device-id-of-file=.

Document that behavior instead of saying positional arguments are
ignored.

Reproducer:
  udevadm info --device-id-of-file=/etc/passwd /sys

Before:
  Devices are not allowed with -d/--device-id-of-file and -c/--cleanup-db.

Follow-up:
  31767b92a0b3980e0ae8a0f44715f86e72c35f77

2 days agoudevadm-settle: reject positional arguments
dongshengyuan [Mon, 13 Jul 2026 02:38:46 +0000 (10:38 +0800)] 
udevadm-settle: reject positional arguments

The settle command does not define positional arguments.

Reject them during argument parsing instead of silently ignoring
them.

Reproducer:
  udevadm settle /no/such/argument

Before:
  The command exits successfully and ignores the argument.

Follow-up:
  c71509028fc2741b25dd537f9e1b7e8896df745e

2 days agoudevadm-wait: let --removed override initialization
dongshengyuan [Mon, 13 Jul 2026 02:36:10 +0000 (10:36 +0800)] 
udevadm-wait: let --removed override initialization

The documentation says --initialized= is ignored when --removed is
specified.

Track --removed separately so it wins regardless of option order.

Reproducer:
  udevadm wait --timeout=0 --removed --initialized=no /dev/no-such-test-device

Before:
  Timed out for waiting devices being added.

Follow-up:
  aa2b0d8d291a1f1dc2b50016c076ff8196989f84

2 days agoudevadm-info: allow valueless attr filters
dongshengyuan [Mon, 13 Jul 2026 02:33:34 +0000 (10:33 +0800)] 
udevadm-info: allow valueless attr filters

The --attr-match= and --attr-nomatch= filters are documented as
FILE[=VALUE], like the trigger filters.

Accept a bare attribute name for sysfs attribute presence matches.

Reproducer:
  udevadm info --export-db --attr-match=ifindex

Before:
  Expected <ATTR>=<value> instead of 'ifindex'

Follow-up:
  a6b4b2fa010f6dc5e18f1a14d93204c6c1416278

2 days agoudev: avoid reading before empty capability masks
dongshengyuan [Mon, 13 Jul 2026 02:30:25 +0000 (10:30 +0800)] 
udev: avoid reading before empty capability masks

When input_id prints a decoded capability bitmap, an all-zero
bitmap can decrement the index to zero.

Check the index before reading bitmask[val - 1].

Reproducer:
  udevadm test-builtin input_id with an all-zero capability mask

Follow-up:
  912541b0246ef315d4d851237483b98c9dd3f992

2 days agoshell-completion: add new Argon2id TPM2 parameters for systemd-cryptenroll 41859/head
fuldeka [Fri, 3 Jul 2026 22:02:18 +0000 (00:02 +0200)] 
shell-completion: add new Argon2id TPM2 parameters for systemd-cryptenroll

2 days agotree-wide: add missing libopenssl_cflags to targets using tpm2-util.h
fuldeka [Fri, 3 Jul 2026 17:33:37 +0000 (19:33 +0200)] 
tree-wide: add missing libopenssl_cflags to targets using tpm2-util.h

tpm2-util.h includes crypto-util.h, which requires OpenSSL compiler
flags when HAVE_OPENSSL is defined. Add libopenssl_cflags to every
build target that uses tpm2_cflags but was missing the transitive
OpenSSL dependency.

2 days agocryptsetup: add Argon2id-based PIN mode for TPM2 enrollment
fuldeka [Sun, 28 Jun 2026 14:42:47 +0000 (16:42 +0200)] 
cryptsetup: add Argon2id-based PIN mode for TPM2 enrollment

The current TPM2 PIN mode is flawed as a compromised TPM directly exposes
the sealed secret which is the LUKS volume key itself (#27502 and #37386).

Goal: add Argon2id-based PIN hardening to TPM2 enrollment, making
the TPM a second factor rather than a single point of failure:

1. Password + salt -> Argon2id -> 512-bit key split into Key1 + Key2
2. Key2 (base64-encoded) is used as the PIN to seal a random secret
in the TPM
3. Key1 + unsealed secret -> HKDF-SHA256 -> final LUKS volume key

This implementation ensures that if the TPM is compromised, an attacker
still needs the password to derive Key1 and combine it with the unsealed
secret.

The --tpm2-with-pin= option now accepts three values:
- false (no PIN used)
- true (PIN hardened with Argon2id - default)
- "direct" (legacy PIN without Argon2id for backward compatibility)

Argon2id parameters are customizable via:

--tpm2-argon2id-memory=
--tpm2-argon2id-iterations=
--tpm2-argon2id-parallelism=
--tpm2-argon2id-iter-time=

These default to a function of available CPUs and physical memory, with
a benchmark that scales iterations to the target time (default: 2s) and
falls back to ARGON2ID_PARAMETERS_DEFAULT (64 MiB, 8 iter, 4 lanes) when
auto detection fails.
Also if the runtime OpenSSL lacks Argon2id support (< 3.2), the feature
silently falls back to direct PIN mode with a warning.

Added includes:
- src/cryptenroll/cryptenroll.c: cpu-set-util.h, limits-util.h, time-util.h
  for Argon2id benchmark auto-tuning (cpus_online, physical_memory_scale,
  now/usec_t)
- src/cryptenroll/cryptenroll-tpm2.c: crypto-util.h for Argon2IdParameters
  struct in load_volume_key_tpm2()
- src/shared/tpm2-util.h: crypto-util.h for Argon2IdParameters in
  tpm2_make_luks2_json() API
- src/shared/tpm2-util.c: limits-util.h, tpm2-util.h for physical_memory() validation
  of Argon2id memory cost and function prototypes
- src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c: crypto-util.h for
  kdf_argon2id_derive()/kdf_hkdf_sha256() on the token unlock path

2 days agomachined: set user.userdb.* xattrs on machined socket
Lennart Poettering [Fri, 10 Jul 2026 07:09:13 +0000 (09:09 +0200)] 
machined: set user.userdb.* xattrs on machined socket

2 days agohomed: set user.userdb xattrs on homed's userdb socket
Lennart Poettering [Fri, 10 Jul 2026 07:07:49 +0000 (09:07 +0200)] 
homed: set user.userdb xattrs on homed's userdb socket

We can't make a lot of restrictions here, since users are allowed to
basically freely pick their user names and UIDs too. But let's at least
exclude system UID ranges and those beyond the 16bit range.

2 days agocore: tag dynamic user userdb provider with dynamic uid/gid ranges
Lennart Poettering [Fri, 10 Jul 2026 04:31:30 +0000 (06:31 +0200)] 
core: tag dynamic user userdb provider with dynamic uid/gid ranges

Let's optimize lookups to PID 1's dynamic UID/GID range feature.

2 days agouserdb: suppress lookups outside of indicated ranges
Lennart Poettering [Thu, 9 Jul 2026 13:35:38 +0000 (15:35 +0200)] 
userdb: suppress lookups outside of indicated ranges

When doing a userdb lookup we might end up issuing a lot of IPC calls in
parallel to backends and cause them all to do work, with us waiting for
it. Let's optimize this a bit, and indicate on the socket inodes via
xattrs hints which kind of records are provided by a backend. That way
we can suppress lookups to them and optimize runtime behaviour.

This only works on Linux 7.1 and newer where socket inodes gained
support for extended attributes.

2 days agouserdb: drop redundant check
Lennart Poettering [Thu, 9 Jul 2026 13:36:01 +0000 (15:36 +0200)] 
userdb: drop redundant check

2 days agosd-varlink: add sd_varlink_call_and_upgradeb() + sd_varlink_call_and_upgradebo() 42974/head
Lennart Poettering [Tue, 7 Jul 2026 10:45:31 +0000 (12:45 +0200)] 
sd-varlink: add sd_varlink_call_and_upgradeb() + sd_varlink_call_and_upgradebo()

This are to the existing sd_varlink_call_and_upgrade() what
sd_varlink_callb() and sd_varlink_callbo() are to sd_varlink_call():
they put together an object on the fly, via the usual JSON builder
logic.

2 days agosd-varlink: add async server-side upgrade API
Lennart Poettering [Tue, 7 Jul 2026 08:47:46 +0000 (10:47 +0200)] 
sd-varlink: add async server-side upgrade API

2 days agosd-varlink: move varlink_handle_upgrade_fds() before sd_varlink_process()
Lennart Poettering [Tue, 7 Jul 2026 09:13:38 +0000 (11:13 +0200)] 
sd-varlink: move varlink_handle_upgrade_fds() before sd_varlink_process()

This is a simple move, in preparation for using this as part of the
sd_varlink_process() callchain.

2 days agosd-varlink: fold separate 'protocol_upgrade' flag into state machine
Lennart Poettering [Tue, 7 Jul 2026 08:59:40 +0000 (10:59 +0200)] 
sd-varlink: fold separate 'protocol_upgrade' flag into state machine

2 days agojson-stream: add helper json_stream_has_buffered_output()
Lennart Poettering [Tue, 7 Jul 2026 08:45:08 +0000 (10:45 +0200)] 
json-stream: add helper json_stream_has_buffered_output()

2 days agoAssorted basic/shared/ndisc/import hardening fixes flagged by kres (#42934)
Lennart Poettering [Sun, 12 Jul 2026 20:17:08 +0000 (22:17 +0200)] 
Assorted basic/shared/ndisc/import hardening fixes flagged by kres (#42934)

2 days agoclaude-review: downgrade effort from xhigh to high
Luca Boccassi [Sun, 12 Jul 2026 09:56:12 +0000 (10:56 +0100)] 
claude-review: downgrade effort from xhigh to high

Claude reviews keep failing due to hitting 60m timeouts, as they take
too long. Lower effort from xhigh to high to try and speed them up.

3 days agohwdb: sensor: Add Odys Windesk X10 accel mount matrix
Hans de Goede [Sun, 12 Jul 2026 11:32:02 +0000 (13:32 +0200)] 
hwdb: sensor: Add Odys Windesk X10 accel mount matrix

Add a mount matrix for the accelerometer on the Odys Windesk X10 tablet to
fix auto-rotation.

3 days agoRevert "claude-review: bump timeout from 60m to 120m"
Luca Boccassi [Sat, 11 Jul 2026 23:46:52 +0000 (00:46 +0100)] 
Revert "claude-review: bump timeout from 60m to 120m"

This reverts commit 6f04b8e5717264c2547f1c3e764ba8b000c23d0c.

3 days agoclaude-review: bump timeout from 60m to 120m
Luca Boccassi [Sat, 11 Jul 2026 18:32:59 +0000 (19:32 +0100)] 
claude-review: bump timeout from 60m to 120m

Claude got slower, but in many cases it's on the brink of finishing the
review when the timeout kicks in. Double it.

3 days agoci: check 'update-man-rules' to ensure it is not forgotten
Luca Boccassi [Sat, 11 Jul 2026 18:47:16 +0000 (19:47 +0100)] 
ci: check 'update-man-rules' to ensure it is not forgotten

We often forget to run this command when updating manpages, and notice
only much later. Add a step in the CI to flag it, as we already do for
the D-Bus docs.

3 days agonss-myhostname: keep IPv6 probe result stable 42934/head
Luca Boccassi [Wed, 8 Jul 2026 14:58:45 +0000 (15:58 +0100)] 
nss-myhostname: keep IPv6 probe result stable

Cache the IPv6 enabled state while sizing and filling NSS result
buffers, so a transient sysctl read result cannot change the tuple or
address layout after the scratch buffer size has been computed. Also
zero-initialize gaih_addrtuple records before filling IPv4 addresses.

Follow-up for e8a7a315391a6a07897122725cd707f4e9ce63d7

3 days agocreds: tolerate TPM2 seal failure in auto mode
Luca Boccassi [Wed, 8 Jul 2026 14:40:59 +0000 (15:40 +0100)] 
creds: tolerate TPM2 seal failure in auto mode

Automatic key modes tolerate a failed TPM2 sealing attempt and
fall back to a host or null key. Do not consume TPM2 blob output in
that case, tpm2_seal() leaves it empty on failure, so the fallback
path should continue without TPM2 metadata.

Follow-up for 9e4379945b74ee7920fe375be0bcb04d8ef53873

3 days agondisc: reject non-zero ICMPv6 codes in parsers
Luca Boccassi [Wed, 8 Jul 2026 13:22:41 +0000 (14:22 +0100)] 
ndisc: reject non-zero ICMPv6 codes in parsers

NDisc packets received through the socket path are filtered before
parser dispatch, but parser entry points should still reject malformed
packet bytes instead of asserting on them. Return EBADMSG for non-zero
ICMPv6 code values in RA, NA, and Redirect messages.

Follow-up for c34cb1d6451dd9fcd36e1c08c553ca7f25e9d83b
Follow-up for 696eb2b8de980a2b79c1de7fbf12195936b00441
Follow-up for 44e8cf303b1e54752637725d55d01811e05ed482

3 days agopull-oci: verify redirected manifest digest
Luca Boccassi [Wed, 8 Jul 2026 12:53:52 +0000 (13:53 +0100)] 
pull-oci: verify redirected manifest digest

An OCI index redirect already carries the digest of the selected
manifest. Store it in the expected checksum field so pull-job
verifies the downloaded manifest instead of overwriting the digest
with the computed checksum before comparison.

Follow-up for a9f6ba04969d6eb2e629e30299fab7538ef42a57

3 days agoefivars: fix concurrent growth read accounting
Luca Boccassi [Wed, 8 Jul 2026 12:07:44 +0000 (13:07 +0100)] 
efivars: fix concurrent growth read accounting

efi_get_variable() allocates one byte for probing whether efivarfs
has grown since fstat(), then three more bytes for NUL termination.
Account for both sizes separately so a full readv() result is treated
as concurrent growth and retried before the terminators are written.

Follow-up for ab69a04600fd34c152c44be6864eb3bc64568e17

4 days agonetwork: do not regenerate MAC address if already set by userspace
Shihao Ren [Fri, 10 Jul 2026 07:26:27 +0000 (15:26 +0800)] 
network: do not regenerate MAC address if already set by userspace

When MACAddress= is unspecified, a stable MAC is generated to seed a newly
created netdev. Since existing netdevs are reconfigured on reload/restart,
this seed got re-applied to an already existing interface, conflicting with
an explicit MACAddress= from the matching .network file and flipping MAC.

Now, when MACAddress= is unspecified, only generate a new address if
addr_assign_type is not NET_ADDR_SET (i.e. not already set by userspace). On
first creation the interface does not exist yet, so this is a no-op and the
address is generated as before. Mirrors src/udev/net/link-config.c.

Fixes: #42457
4 days agocreds-util: implement TPM2 SRK pinning
Popax21 [Thu, 19 Mar 2026 02:33:26 +0000 (03:33 +0100)] 
creds-util: implement TPM2 SRK pinning

Stores the TPM2 SRK within the credential header, allowing for parameter decryption to be utilized when decrypting the credential.
A new dimension is added to the credential ID matrix to encode this capability.

This also allows for usage of TPM2-bound credentials when a TPM owner password is set since `Esys_CreatePrimary` is no longer used for sealing credentials.

4 days agocreds: allow normal users to encrypt with`--with-key=null`
Michael Vogt [Fri, 10 Jul 2026 15:27:11 +0000 (17:27 +0200)] 
creds: allow normal users to encrypt with`--with-key=null`

When encrypting with the `--with-key=null` option systemd-creds
is currently doing the encryption via IPC. This is not needed
for the null key, no privs are required so we can just do the
in-process operation. So instead simply check for the null-key and
if its requested use the in-process path.

4 days agoman: run forgotten 'update-man-rules'
Lennart Poettering [Tue, 7 Jul 2026 10:58:50 +0000 (12:58 +0200)] 
man: run forgotten 'update-man-rules'

4 days agomkosi: update debian commit reference to b322b8d98e0192763aa711dc2aa2f98d8276aae3
Luca Boccassi [Fri, 10 Jul 2026 13:39:08 +0000 (14:39 +0100)] 
mkosi: update debian commit reference to b322b8d98e0192763aa711dc2aa2f98d8276aae3

b322b8d98e Install new files for upstream build
3fd1b81c94 Update changelog for 261.1-3 release
8f95f1370c Move modules-load from systemd package to udev package
bcdf90c670 debian/libpam-systemd.postinst: pam-auth-update does not use getopt
743e3399ac d/README.source: document policy for adding new binary packages
cbea74783c Install new files for upstream build
ef267b3ad6 debian/libpam-systemd.postinst: run pam-auth-update with --root=$DPKG_ROOT
54df2859b4 d/t/upstream: use mkosi from archive for Ubuntu autopkgtest
21959e8a59 Fix zsh installation path, again
f01dddb047 Fix zsh installation path
e31737edc4 Install new files for upstream build
ca0630a51e Update changelog for 261.1-2 release
1ebb987599 d/t/control: pull in cpio for upstream suite
fcf5a24f47 Two more fixups for d/copyright
6ad198086d d/t/control: pull new packages in upstream test suite
bb9fd757fd Make systemd actually temporarily depend on systemd-tpm

4 days agosysupdate: enable/disable verb for features and components (#42947)
Lennart Poettering [Fri, 10 Jul 2026 15:23:22 +0000 (17:23 +0200)] 
sysupdate: enable/disable verb for features and components (#42947)

These are the next 3 commits from #42651. Split out again, in the hope
to get a review from claude.

ptal.

full test suite and docs are in #42651. test suite passed there.

5 days agoobs: explicitly disable Ubuntu/i586 builds
Luca Boccassi [Fri, 10 Jul 2026 13:01:50 +0000 (14:01 +0100)] 
obs: explicitly disable Ubuntu/i586 builds

i586 is a partial architecture on Ubuntu, so package builds cannot
work, explicitly disable it to avoid visual clutter in the build
report page.

5 days agoman: drop '\r' from systemd-clonesetup.xml
Yu Watanabe [Fri, 10 Jul 2026 12:40:55 +0000 (21:40 +0900)] 
man: drop '\r' from systemd-clonesetup.xml

Follow-up for 104970a8bd7a3b53067f6e50283183406a579f0b.

5 days agocredentials: add policy that can allow key=null creds from the ESP (#42555)
Lennart Poettering [Fri, 10 Jul 2026 12:43:12 +0000 (14:43 +0200)] 
credentials: add policy that can allow key=null creds from the ESP (#42555)

This PR only sets the default to "relaxed" - I can change the default
to "tofu" if desired. But for that we will also need to update the NEWS
file to ensure everyone is aware of this new default.

---

This PR adds a new `systemd.credentials-boot=` kernel
commandline that allows to control if credentials with
a `null` key are accepted.

The possible options are:
* strict: always insist on tpm encryption
* tofu: allow null encryption in firstboot mode and when no tpm is
available
* relaxed: allow null encryption when sb is off, or no tpm is available
* off: allow null encryption always

The default is `relaxed` which is exactly the behavior we had before.

This replaces the initial idea of using plaintext credentials
at firstboot (thanks to Lennart for this nicer and simpler design).

---

With that we can drop `- firstboot: optionally accept credentials at
firstboot without authentication` from TODO.md

5 days agoAdd support for aarch64 CPUFeatures (#42902)
Lennart Poettering [Fri, 10 Jul 2026 12:41:01 +0000 (14:41 +0200)] 
Add support for aarch64 CPUFeatures (#42902)

Extend real_has_cpu_with_flag to support aarch64 CPU Features using
hwcaps.

With this PR, users can find out if their Arm system supports
architecture-specific features such as BTI as follows:

```
$ systemd-analyze condition 'ConditionCPUFeature=bti'
```

5 days agosysupdate: move cleanup verb up close to "vacuum" 42947/head
Lennart Poettering [Wed, 24 Jun 2026 10:52:09 +0000 (12:52 +0200)] 
sysupdate: move cleanup verb up close to "vacuum"

These are philosophically similar concepts: one deletes old versions
based on whether they are old, and the other deletes old files based on
whether they are orphaned, let's list them together.

5 days agosysupdate: tighten component_name_valid() mildly
Lennart Poettering [Fri, 10 Jul 2026 12:36:31 +0000 (14:36 +0200)] 
sysupdate: tighten component_name_valid() mildly

Let's make sure that we can still generate a component enablement
drop-in for any component that might be defined.

5 days agosysupdate: add new enable-component/disable-component verb
Lennart Poettering [Wed, 24 Jun 2026 10:50:29 +0000 (12:50 +0200)] 
sysupdate: add new enable-component/disable-component verb

This mimics the enable-feature/disable-feature verbs, but operates on
whole components, not features.

5 days agosysupdate: add enable-feature/disable-feature verbs
Lennart Poettering [Wed, 24 Jun 2026 10:35:01 +0000 (12:35 +0200)] 
sysupdate: add enable-feature/disable-feature verbs

These do what updatectl's verbs of the same name does, but are
implemented as low-level concepts in sysupdate itself.

(The idea is to eventually wrap this in Varlink IPC, and make updatectl
use them that way.)

5 days agosysupdate: generalize feature name validity check
Lennart Poettering [Fri, 10 Jul 2026 12:34:59 +0000 (14:34 +0200)] 
sysupdate: generalize feature name validity check

Let's switch to string_is_safe(), and make this available to the rest of
the sysupdate sources too.

This both relaxes and tighten the rules slightly. i.e. control character
and stuff are no longer allowed, but valid UTF-8 (as opposed to ASCII)
now is.

5 days agosysupdate: explicitly refuse --root=/--image= in conjunction with --definitions=
Lennart Poettering [Fri, 10 Jul 2026 08:53:12 +0000 (10:53 +0200)] 
sysupdate: explicitly refuse --root=/--image= in conjunction with --definitions=

This is currently effectively not supported (as we sometimes prefix the
definitions path with root and sometimes not), let's make this official
for now and refuse it. We could in theory support the combination but I
don't see the big benefit of it for now, hence let's just refuse it.

5 days agosysupdate: Evaluate all patterns before descending into a subdir
Kai Lüke [Fri, 3 Jul 2026 13:39:22 +0000 (22:39 +0900)] 
sysupdate: Evaluate all patterns before descending into a subdir

When we have two match patterns, e.g., because the repository layout
changed and we look for old and new style files, we can have the case
that one pattern suggests a descend into a subdir but the other pattern
would be a direct match. This was missed and only the descent was done.
Yet the other way round also has to be covered: We can't just use the
direct match because it might be that it's rejected if the type doesn't
fit (directory vs. regular file). In this case we should still descent.

Remember that we want to descend but continue checking the other
pattern first to maybe get a direct match. Introduce a new combined
return code YES_AND_RETRY to give the full information to the caller
which now can decide to fallback to a descent. While at it, use the
stat info for the directory check. Also add tests to ensure that the
order of patterns doesn't matter and we handle the above corner cases.

5 days agosysupdate: Support matching for filenames in subdirectories
Kai Lüke [Thu, 14 May 2026 14:28:38 +0000 (23:28 +0900)] 
sysupdate: Support matching for filenames in subdirectories

While for sysupdate it's fine to consume a large set of all possible
update payloads in a single directory this is not so handy for managing
and serving the update payloads. Since this large update folder is not
where the build output directly gets written to one has to create
copies and later possibly delete this added set of files.

Support matching for filenames in subdirectories by having a new **/
match pattern prefix which matches any number of nested subdirectories
or no subdirectory at all. For simplicity it's only allowed at the start
of a pattern and not a regular wildcard as the rest because the main
use case is to descend into subdirectories and only do the pattern
matching for the basenames. This way one can create a SHA256SUMS file
in the top folder and have it include all update payloads from the
release-specific (or arch-specific) subdirectories. Something similar
was already supported for directory sources where the match pattern can
start with a subdirectory path. Do also support this for SHA256SUMS for
parity while we are at it. Having the new wildcard makes mirroring also
easier because one does not have to follow the exact subdirectory layout
and one can filter by folder instead of by filename. It also makes it
possible to point the same transfer files with the new wildcard to
either a SHA256SUMS file that uses release-specific (or arch-specific)
subdirectories and includes all versions or to a SHA256SUMS file as
generated from mkosi that does not use subdirectories because it only
has files for a single version.
With the upcoming UAPI.16 JSON format we will also be able to encode
subdirectories and it makes sense to add this to SHA256SUMS for being
able to convert them. It also supports custom URLs for each entry which
is more powerful than the (arbitrary) subdirectory feature used here but
subdirectories have the advantage that they don't break mirroring.
This change also fixes the existing subdirectory handling bugs where
everything greater than two subdirectory levels failed to work because
rel_joined instead of de->d_name got used, symlinks were followed, and
we would continue silently on non-ENOENT errors.

5 days agoclonesetup: add support to clone devices via /etc/clonetab
Simran Singh [Wed, 10 Dec 2025 00:44:53 +0000 (06:14 +0530)] 
clonesetup: add support to clone devices via /etc/clonetab

Adds dm-clone device setup at boot via a new /etc/clonetab config file,
following the crypttab/veritytab pattern.

- Add systemd-clonesetup-generator to parse /etc/clonetab and generate units.
- Add systemd-clonesetup binary to create/remove dm-clone devices via ioctl.
- Add clonesetup.target for ordering dm-clone activation at boot.
- Add region_size= option in clonetab to configure dm-clone hydration granularity.
- Add clonetab(5) and systemd-clonesetup-generator(8) man pages.

Fixes: https://github.com/systemd/systemd/issues/39500
5 days agoudev: require exact builtin command matches
dongshengyuan [Thu, 9 Jul 2026 12:30:44 +0000 (20:30 +0800)] 
udev: require exact builtin command matches

Commit 9b917abe02505d4ad09c4963ec5a4b2744eb2fee (udev-builtin:
simplify code a bit) changed builtin lookup from copying the first
command word and comparing it with streq() to comparing only the first
command word length with strneq().

That made prefixes such as "k" or "key" resolve to the "keyboard"
builtin, depending on the builtins table order. This was not the
original behavior.

Require the matched builtin name to end at the first command word
boundary so only complete builtin names are accepted. Arguments after
the builtin name continue to work as before.

5 days agoudev: fix several reproducible command handling issues (#42958)
Yu Watanabe [Fri, 10 Jul 2026 11:04:51 +0000 (20:04 +0900)] 
udev: fix several reproducible command handling issues (#42958)

This PR fixes several independent udev command and rule handling issues.
Each commit contains the corresponding reproducer and fix details.

5 days agoman: document arm64 CPUFeatures 42902/head
Emanuele Rocca [Mon, 6 Jul 2026 12:17:37 +0000 (14:17 +0200)] 
man: document arm64 CPUFeatures

Signed-off-by: Emanuele Rocca <emanuele.rocca@arm.com>
5 days agovirt: support architecture prefixes in CPUFeature
Emanuele Rocca [Fri, 10 Jul 2026 08:26:27 +0000 (08:26 +0000)] 
virt: support architecture prefixes in CPUFeature

Extend ConditionCPUFeature to support architecture prefixes in feature names.
The goal is avoiding ambiguities on mixed-arch fleets, where CPU feature names
may potentially conflict.

With this patch, ConditionCPUFeature=arm64.bti is now equivalent to
ConditionCPUFeature=bti on arm64 systems.

Signed-off-by: Emanuele Rocca <emanuele.rocca@arm.com>
5 days agovirt: add support for aarch64 CPU Features
Emanuele Rocca [Mon, 6 Jul 2026 12:16:12 +0000 (14:16 +0200)] 
virt: add support for aarch64 CPU Features

Extend real_has_cpu_with_flag to support aarch64 CPU Features using hwcaps.

With this patch, users can find out if their Arm system supports
architecture-specific features such as BTI as follows:

$ systemd-analyze condition 'ConditionCPUFeature=bti'

Signed-off-by: Emanuele Rocca <emanuele.rocca@arm.com>
5 days agoinclude: add hwcaps missing from glibc and musl
Emanuele Rocca [Mon, 6 Jul 2026 12:13:31 +0000 (14:13 +0200)] 
include: add hwcaps missing from glibc and musl

Add an override file for all capabilities missing in glibc v2.34 and musl
1.2.6. The constant AT_HWCAP3 is also not in glibc v2.34, ship a glibc-specific
elf.h in order to provide it.

Signed-off-by: Emanuele Rocca <emanuele.rocca@arm.com>
5 days agoOptimize dlopen ELF notes via anchoring and explicitly embed them into executables...
Yu Watanabe [Fri, 10 Jul 2026 08:37:39 +0000 (17:37 +0900)] 
Optimize dlopen ELF notes via anchoring and explicitly embed them into executables (#42908)

This PR optimizes the handling of `dlopen` ELF notes and reduces binary
footprints across the tree.

By enabling compiler section-splitting
(`-ffunction-sections`/`-fdata-sections`), the linker can now accurately
garbage-collect unused code and data. To align with this,
`SD_ELF_NOTE_DLOPEN_ANCHORED()` macro is introduced, which ties `dlopen`
notes to their calling functions so that unused notes are automatically
removed by `--gc-sections`.

Additionally, this explicitly embeds required `dlopen` notes into
individual executables to fix a visibility issue where package managers
missed runtime dependencies invoked indirectly through
`libsystemd-shared.so`.

5 days agorun: recognize clock change timer properties (#42949)
DongShengyuan [Fri, 10 Jul 2026 08:35:19 +0000 (16:35 +0800)] 
run: recognize clock change timer properties (#42949)

--on-clock-change and --on-timezone-change are documented as shortcuts for
setting the corresponding timer properties with --timer-property=.

However, --timer-property= only treated the monotonic and calendar timer
settings as actual timer triggers. OnClockChange= and OnTimezoneChange=
were stored as timer properties, but arg_with_timer remained false and the
command was rejected as having no timer options.

Treat both properties as timer triggers too, matching the shortcut options
and the documented equivalent command line.

5 days agonspawn-oci: match the spec-correct "swappiness" memory field key
hanjinpeng [Wed, 8 Jul 2026 07:07:01 +0000 (03:07 -0400)] 
nspawn-oci: match the spec-correct "swappiness" memory field key

The OCI runtime specification names the memory swappiness knob
"swappiness" (memory.swappiness), but the dispatch table
in oci_cgroup_memory() registered it as "swapiness".

Since sd_json_dispatch_full() matches object keys by exact string
comparison, a spec-correct config carrying "swappiness" never hit the
intended oci_unsupported() handler and was instead routed to the
bad-field callback oci_unexpected(), which returns -EINVAL and thus
fails the whole memory cgroup section.

Register the correct key so that real OCI bundles parse, keep the
misspelt one around for compatibility, mark both as such, and drop the
now-resolved reminder from the file header TODO list.

5 days agoudevadm-info: handle missing data db cleanup 42958/head
dongshengyuan [Fri, 10 Jul 2026 08:09:34 +0000 (16:09 +0800)] 
udevadm-info: handle missing data db cleanup

udevadm info --cleanup-db cleaned links and tags by comparing them
against /run/udev/data, but asserted when that data directory was
missing.

Treat a missing data directory as an empty database, so stale link
and tag entries can be removed without aborting.

Add a database test that runs cleanup-db with links and tags present
but no data directory.

Reproducer:

$ sudo unshare --mount --propagation private sh -c '
mount -t tmpfs tmpfs /run/udev
mkdir -p /run/udev/links/foo
udevadm info --cleanup-db
'
Assertion 'datadir' failed at src/udev/udevadm-info.c:676, function cleanup_dirs_after_db_cleanup(). Aborting.
Aborted (core dumped)

The command should handle a missing /run/udev/data directory instead
of aborting.

5 days agoudevadm-control: reject oversized children-max
dongshengyuan [Fri, 10 Jul 2026 08:08:07 +0000 (16:08 +0800)] 
udevadm-control: reject oversized children-max

The --children-max= option parsed into an unsigned value and then
stored it in an int sentinel field.

Values above INT_MAX could wrap negative and make the command look as
if no control option had been specified.

Reject oversized values before assigning the parsed value.

Reproducer:

$ udevadm control --children-max=2147483648
No control command option is specified.
$ echo $?
1

The value should be rejected as out of range instead of being wrapped
into the unset sentinel value.

5 days agoudev-rules: drop truncated import output line
dongshengyuan [Fri, 10 Jul 2026 08:05:24 +0000 (16:05 +0800)] 
udev-rules: drop truncated import output line

When IMPORT{program} output was truncated, the code intended to drop
the last incomplete result line before importing properties.

It edited the command buffer instead of the output buffer, so the
incomplete line could still be parsed and imported.

Trim the result buffer and cover the behavior with the existing IMPORT
test.

Follow-up for 6b6e471a325bf149839c5c822b4ae3e66cb1d9a3.

Reproducer:

Configure an IMPORT{program} rule whose output exceeds UDEV_LINE_SIZE
and ends with an incomplete property line, for example:

TRUNCATED_OK=yes
TRUNCATED_BAD=<very long value without terminating newline>

Only TRUNCATED_OK should be imported. Before this fix, the truncation
handler edited the command buffer instead of the output buffer, so
TRUNCATED_BAD could still be parsed from the truncated result.

5 days agoudevadm-hwdb: honor root when querying
dongshengyuan [Fri, 10 Jul 2026 08:05:07 +0000 (16:05 +0800)] 
udevadm-hwdb: honor root when querying

The deprecated udevadm hwdb command parsed --root for both update and
test modes, but the test path always queried the host database.

Pass the configured root to hwdb_query() so --root affects --test in
the same way as systemd-hwdb query.

Reproducer:

$ tmp=$(mktemp -d)
$ mkdir -p "$tmp/etc/udev/hwdb.d"
$ printf 'test:codex-root-test\n ID_TEST_CODEX=from-root\n' > "$tmp/etc/udev/hwdb.d/99-codex.hwdb"
$ systemd-hwdb --root="$tmp" update
$ systemd-hwdb --root="$tmp" query test:codex-root-test
ID_TEST_CODEX=from-root
$ udevadm hwdb --root="$tmp" --test=test:codex-root-test
udevadm hwdb is deprecated. Use systemd-hwdb instead.

The last command was expected to print ID_TEST_CODEX=from-root, but
queried the host database instead.

5 days agoudev-rules: accept cvm CONST matches
dongshengyuan [Fri, 10 Jul 2026 08:04:31 +0000 (16:04 +0800)] 
udev-rules: accept cvm CONST matches

CONST{cvm} is documented and already handled when udev rules are
executed, but the parser rejected it before the rule could be used.

Include cvm in the supported CONST key list.

Follow-up for 6e2e83b48734e86992cbdbb329c48cc066cf7c96.

Reproducer:

$ printf 'CONST{cvm}=="none", NAME="x"\n' > /tmp/codex-cvm.rules
$ udevadm verify /tmp/codex-cvm.rules
/tmp/codex-cvm.rules:1 Invalid attribute for CONST.
/tmp/codex-cvm.rules: udev rules check failed.

1 udev rules files have been checked.
  Success: 0
  Fail:    1

5 days agocondition: split condition_test_list() to minimize dlopen dependencies 42908/head
Yu Watanabe [Thu, 9 Jul 2026 03:47:04 +0000 (12:47 +0900)] 
condition: split condition_test_list() to minimize dlopen dependencies

Even though systemd-networkd and systemd-udevd do not support
ConditionSecurity= in .network, .netdev, and .link files, the unified
condition_test() function maintained a function pointer table that
unconditionally referenced condition_test_security(). Consequently,
linker garbage collection (--gc-sections) could not drop the security
test code, inadvertently pulling in dlopen dependencies and ELF notes
for apparmor, audit, and tpm2 libraries into these binaries.

To resolve this, introduce condition_test_net() and condition_test_list_net(),
which utilize a trimmed-down function pointer table that excludes
security-related condition evaluators.

By migrating networkd and udevd to these new network-specific variants,
the reference to condition_test_security() is completely severed in
their dependency chains. This allows the compiler and linker to
successfully garbage-collect the unused security logic and safely drops
the unnecessary dlopen notes from those binaries.