Commit Graph

10322 Commits

Author SHA1 Message Date
Luca Boccassi
bd7c113e24 boot: honour "read-only" vfat flag on random seed file (#43012)
Inspired by #42979
2026-07-14 11:51:43 +01:00
Luca Boccassi
a5ac81ae4c systemd-run: reject unsupported option combinations (#43003)
Boundary tests were conducted on the "run" command tool, and the
identified issues were resolved.
2026-07-14 11:29:11 +01:00
hanjinpeng
0e7033215d man: clarify that --when= is a lower bound, not a condition
`systemctl reboot --when=yesterday` reboots the machine immediately, which
surprised users enough to be reported as a bug. It is not one: the timestamp
passed to --when= (and to ScheduleShutdown(), and to shutdown(8)) declares the
earliest point in time the action may be taken, it is not a condition that is
evaluated and that could fail.

Behaving any differently would be racy and surprising: "--when=now" refers to
the past by the time the request is processed, and "--when=+50ms" may well have
elapsed already due to scheduling latencies. In both cases we must still carry
out the action the user asked for.

Document the semantics explicitly in systemctl(1), shutdown(8) and the
org.freedesktop.login1(5) D-Bus interface documentation.

Fixes: #42437
2026-07-14 09:43:12 +01:00
Lennart Poettering
78f81f02e8 boot: skip random seed handling if seed file is marked read-only
If the read-only FAT file attribute is set on /loader/random-seed,
don't update the seed file — and hence don't use it either, since a
seed we cannot update would be the same on every boot.

This gives users an explicit way to turn off random seed handling by
marking the file read-only, useful for example in pre-built OS images
that are replicated to many systems, where the baked-in seed is shared
and hence must not be credited.

The check is done upfront in process_random_seed(), before any other
work, mirroring the existing check for read-only volumes. This covers
both systemd-boot and systemd-stub, which share this code.

Inspired-by: #42979
2026-07-14 10:12:50 +02:00
dongshengyuan
06247b0804 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 2a453c2ee3
2026-07-14 12:03:22 +08:00
dongshengyuan
7e76e93142 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 744ca8f616
2026-07-14 12:03:22 +08:00
dongshengyuan
dd6c127d6b 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 1072d94731
2026-07-14 12:03:22 +08:00
Luca Boccassi
1fcd92a214 sysupdate: add "suggestion" concept to feature and component enablement (#42970) 2026-07-13 19:07:50 +01:00
Lennart Poettering
c8cffba715 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
2026-07-13 17:55:47 +02:00
Lennart Poettering
40e727c93b 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.
2026-07-13 17:36:10 +02:00
Luca Boccassi
2e1c8bc3d7 udev: fix several option parsing edge cases (#42997)
Boundary tests were conducted on the udev subsystem, and some issues
were identified and resolved.
2026-07-13 13:42:27 +01:00
Luca Boccassi
061490432e repart: Some fixes for --copy-from= (#42976)
A bunch of things I noticed that aren't correct about `--copy-from` and
grain sizes + paddings.
2026-07-13 13:33:24 +01:00
Jonas Dreßler
0df5ebc079 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.
2026-07-13 12:09:43 +02:00
dongshengyuan
e8dd0bfbbe 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:
  31767b92a0
2026-07-13 12:18:49 +08:00
fuldeka
f3fe668cdf 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
2026-07-12 23:31:29 +02:00
Lennart Poettering
953d21846a 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.
2026-07-12 22:44:03 +02:00
Lennart Poettering
746d10d106 sd-varlink: add async server-side upgrade API 2026-07-12 22:44:03 +02:00
Popax21
70cfb11d4b 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.
2026-07-11 15:37:46 +01:00
Lennart Poettering
4f2521feca man: run forgotten 'update-man-rules' 2026-07-10 21:43:27 +01:00
Yu Watanabe
900c10467a man: drop '\r' from systemd-clonesetup.xml
Follow-up for 104970a8bd.
2026-07-10 14:22:17 +01:00
Lennart Poettering
5cead3f269 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
2026-07-10 14:43:12 +02:00
Lennart Poettering
091bd0ed21 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'
```
2026-07-10 14:41:01 +02:00
Kai Lüke
761c664110 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.
2026-07-10 14:25:38 +02:00
Simran Singh
104970a8bd 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
2026-07-10 14:01:24 +02:00
Emanuele Rocca
6f9bfb0e06 man: document arm64 CPUFeatures
Signed-off-by: Emanuele Rocca <emanuele.rocca@arm.com>
2026-07-10 12:02:54 +02:00
Michael Vogt
cb7f95ff5f credentials: add policy that can allow key=null creds from the ESP
This commit adds a new `systemd.credentials_boot_policy=` 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 currently `relaxed` which is the same behavior
as before.

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

Note that this also moves `in_first_boot()` to `basic/initrd-util`
which is a better fit now.
2026-07-09 16:48:26 +02:00
Michael Vogt
c944af8459 tree-wide: fix some double word errors like "the the"
By chance (because I had this mistake in my own commit) I noticed
that there are a bunch of duplicated works like "the the" in the
code and man-pages.

This commit fixes them and some similar issues with "and and" etc.
2026-07-09 13:09:52 +01:00
Lennart Poettering
7ab48accb2 vmspawn: discover firmware descriptors, opt-in secure boot support for coco (#42876) 2026-07-07 08:55:10 +02:00
Paul Meyer
6f2f5b96f1 vmspawn: allow opt-in Secure Boot firmware for coco
CoCo firmware is stateless, so Secure Boot keys cannot be enrolled at
runtime: it only enforces Secure Boot with keys baked in at build time,
refusing unsigned images from the first boot. The default exclusion of
the enrolled-keys firmware feature hence keeps unsigned images bootable,
but it also makes firmware discovery fail on distros that only ship
SNP/TDX firmware with pre-enrolled keys (e.g. Fedora's TDVF). Drop the
rejection of --secure-boot=yes with --coco= and instead treat it as an
opt-in to such firmware, by lifting the enrolled-keys exclusion.

While at it, reject --efi-nvram-template= and an explicit
--efi-nvram-state= path with --coco=, which were silently ignored, as
stateless firmware has no NVRAM to instantiate or persist.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
2026-07-06 11:04:11 +02:00
Paul Meyer
fc077f05d7 vmspawn: select coco firmware via fw descriptors
Instead of requiring --firmware= to point at a raw .fd image for
--coco=sev-snp/tdx, pick a suitable firmware automatically from the
QEMU firmware descriptors, requiring the amd-sev-snp/intel-tdx feature.
CoCo firmware is stateless (it carries no NVRAM template), so teach
find_ovmf_config() to select stateless raw-format firmware via new
flags. --firmware= now uniformly takes a firmware descriptor path.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
2026-07-06 11:02:04 +02:00
Lennart Poettering
805742a9c5 Allow systemd to be built as as single statically-linked binary (#42820)
The idea is that we can build a container by building a single-binary
systemd:
```console
$ meson setup build-static --default-library=static --prefer-static --auto-features=disabled -Dbuild-static=true -Dsystemd-multicall-binary=true && ninja -C build-static systemd
$ mkdir /var/tmp/container/usr/lib -p
$ cp build-static/systemd /var/tmp/container/usr/lib/
$ echo 'ID=quick' >/var/tmp/container/usr/lib/os-release
$ systemd-nspawn --restrict-address-families=af_unix --register=no --private-users=managed -D /var/tmp/container/ /usr/lib/systemd
░ Spawning container container on /var/tmp/container.
░ Press Ctrl-] three times within 1s to kill container; two times followed by r
░ to reboot container; two times followed by p to poweroff container.
Selected user namespace base 1855193088 and range 65536.
systemd 262~devel running in system mode (-PAM -AUDIT +SELINUX -APPARMOR +IMA +IPE +SMACK -SECCOMP -GCRYPT +GNUTLS +OPENSSL -ACL +BLKID +CURL -ELFUTILS -FIDO2 +IDN2 +KMOD +LIBCRYPTSETUP +LIBCRYPTSETUP_PLUGINS +LIBFDISK +PCRE2 -PWQUALITY +P11KIT +QRENCODE +TPM2 -BZIP2 -LZ4 +XZ +ZLIB +ZSTD -BPF_FRAMEWORK -BTF -XKBCOMMON +UTMP -LIBARCHIVE)
Detected virtualization systemd-nspawn.
Detected architecture x86-64.
Detected first boot.

Welcome to Linux!

Initializing machine ID from container UUID.
Failed to open netlink, ignoring: Address family not supported by protocol
Applying preset policy.
Populated /etc with preset unit settings.
Unit default.target not found.
Falling back to graphical.target.
Mount unit not supported, skipping *MountsFor= dependencies.
Queued start job for default target graphical.target.
[  OK  ] Reached target sysinit.target.
[  OK  ] Reached target basic.target.
System is tainted: unmerged-bin:var-run-bad
[  OK  ] Reached target multi-user.target.
[  OK  ] Reached target graphical.target.
Startup finished in 61ms.
```
The container can be reloaded with SIGTERM, powered off with SIGRTMIN+4,
etc. SIGRTMIN+5 should cause a reboot but it currently fails:
```
...
Rebooting.
Container container is being rebooted.
Failed to attach root directory: Invalid argument
Failed to receive mount namespace fd from outer child: Input/output error
```
It's a bug … somewhere, but probably not caused by the linking changes
being done here.
2026-07-02 21:56:27 +02:00
Chris Coulson
2348941b5d measure: Support binding signed policies to individual phases
systemd-measure can produce multiple signed policies for different
phases. However, a policy for a TPM resource that includes these signed
policies can currently be satisfied by any policy that is signed
with the same key.

It can be desirable to bind a resource's policy to one or more
specific phases. One way to do this could be to sign policies for
different phases or phase combinations with different keys. Another
approach is to limit the scope of signed policies using a policy
reference.

Using a policy reference works because:
- The reference is included along with the approved policy digest in the
  digest that is signed.
- The reference argument is included in the authorization policy for a
  resource via the TPM2_PolicyAuthorize assertion.
- During execution of the TPM2_PolicyAuthorize assertion, the TPM checks
  that the session's current policy digest is the approved policy digest,
  computes a digest from the approved policy digest and the supplied policy
  reference, and checks that the resulting digest is the one that was
  verified by TPM2_VerifySignature (via the returned ticket).

This adds a new --policyref argument to systemd-measure which binds all
of the signed policies to the specified policy reference. I did consider
making this more intelligent by auto-generating policy references for each
phase, but this approach provides the most flexibility for now. By making
use of the existing --append argument, a signer can produce multiple
signed policies with the same key that are bound to any individual phases
or combinations of phases.

The policy reference is a string without the NULL terminator. It is
supplied to the TPM via the TPM2B_NONCE type, which has a maximum size
equivalent to the size of the largest digest supported by the TPM. As
the signer doesn't know the capabilities of the target TPM,
systemd-measure limits the size of the policy reference to 32 bytes, to
fit within the size of a SHA256 digest.

This also includes the corresponding changes to systemd-cryptenroll and
systemd-repart (to add an equivalent --tpm2-public-key-policyref argument
so that the policy can be bound to the desired corresponding phase, and to
ensure that the policy reference is included in the LUKS2 token metadata),
and systemd-cryptsetup (to handle the policy reference stored in the LUKS2
token metadata).

This doesn't include policy reference support for credentials yet
because it requires a change to the credential headers.
2026-07-02 21:28:42 +02:00
Luca Boccassi
964f0607e4 man: add thread-awareness note to sd_bus/sd_event manpages
This question comes up every now and then, and it is not clearly documented,
so include the thread-aware tag in all bus/event manpages.
2026-07-02 17:04:07 +01:00
Luca Boccassi
243fcc6200 man: note that sd-tmpfiles/sysusers --root is not a sandboxing feature
This seems to be causing enough confusion that it is worth explicitly
mentioning in the docs
2026-07-02 17:02:40 +01:00
Zbigniew Jędrzejewski-Szmek
a809b6e565 core: add fallback-default-target build option
Add a 'fallback-default-target' meson option that configures which unit
to activate when default.target is not installed. This makes things more
resilient in general and is also useful for minimal/statically-linked
installations that may not ship a default.target symlink.

'graphical.target' is used as the default value of the setting, because
that's what we symlink as default.target in units/meson.build.

In the initrd, we had a fallback to start default.target if initrd.target
cannot be started. This fallback is changed to only do that if it is
not found, not on other errors. This seems more correct (and makes
the two fallbacks symmetrical.)
2026-07-02 17:19:18 +02:00
Paul Meyer
1ef7c15bd8 ukify: show all sections and profiles in inspect JSON output
The JSON output keyed every section by name, so a UKI with repeated
sections only showed the last one: in a multi-profile UKI all but one
.profile/.cmdline/.pcrsig were dropped, as were extra .dtbauto/.efifw.

Report the shared base sections by name at the top level (so .cmdline
etc. stay where they were), each profile as its own by-name object under
a new "_profiles" array, and the alternative-set sections (.dtbauto,
.efifw) as arrays.

Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Paul Meyer <katexochen0@gmail.com>
2026-07-02 13:26:33 +02:00
Michael Vogt
896fd702ba firstboot: add new systemd.firstboot=headless mode
This adds a new systemd.firstboot=headless mode. It differs from the
existing systemd.firstboot=no mode in that it still performs the
non-interactive auto-configuration that requires no user input (such
as selecting the only installed locale, or applying settings provided
via credentials), and only skips the prompts that would otherwise
block waiting for user input. In contrast, =no disables that
auto-configuration along with the prompts.

The option is also honoured by homectls firstboot logic and
systemd-cryptenroll, where headless behaves the same as no
(because the is no auto-configuration).
2026-07-02 09:52:21 +01:00
Shihao Ren
48dc1bbd09 run: refuse --no-block when combined with --scope
In the systemd-run --scope mode, --no-block has no actual effect and will
be silently ignored. Therefore, this combination is explicitly rejected to
reduce confusion for users when using it.

Fixes: #42806
2026-07-01 23:37:44 +02:00
Lennart Poettering
62db9abc38 vmspawn: add Intel TDX confidential VM support (#42835) 2026-07-01 22:14:09 +02:00
Chris Coulson
5a80137aa4 tpm2-setup: Create and persist an endorsement key
This updates systemd-tpm2-setup to create and persist an endorsement
key if there isn't one already. For each supported EK template profile,
it will read the EK certificate from its NV index if there is one.
When there is an EK certificate present, a primary key is created using
the corresponding template. If the resulting EKpub matches the public
key in the certificate, the created EK is persisted and the process is
complete.

The low-range templates and the high-range RSA 2048/3072 and ECC NIST
P256/P384 storage templates are supported, as detailed in section
5.3 of the "TCG EK Credential Profile For TPM Family 2.0" spec v2.7.
High-range templates are preferred because these permit EK usage without
requiring knowledge of the authorization value for the endorsement
hierarchy, meaning that, like with the SRK, it is possible to restrict
the usage of the endorsement hierarchy whilst still permitting use of
the persistent EK.

The EK is always persisted at handle 0x81010001. This handle is
reserved in Table 2 of the "TCG TPM v2.0 Provisioning Guidance" spec
v1.0r1.0, although this is only a recommendation. This
handle is within the block of handles reserved for endorsement
primary keys in the "Registry of Reserved TPM 2.0 Handles and
Localities" spec v1.2r1.00. Section 2.3.2 of this specification also
makes a suggestion that there should be a relationship between the EK
certificate NV index and a corresponding persistent EK handle by
using handles at the same offsets within their respective ranges.
However, this contradicts the provisioning guidance spec which reserves
0x81010001 when there isn't a certificate at 0x01c00001. For simplicity,
I've chosen to use a single handle for the EK regardless of which profile
it is created with.

The "TCG EK Credential Profile For TPM Family 2.0" spec also provides a
way for endorsement keys to be certified with non-standard templates by
storing the template in a NV index. This is also supported.

The EK creation is not executed with tpm2-setup --early, as there's no
need for it to be created so early, unlike with the SRK. I also haven't
stored EKpub in /var/lib/systemd like with the SRKpub, as I'm not sure
there will be a use case for this yet.

A follow-up PR may be needed to add some internal helpers to make use
of the persisted EK, as use of low-range EKs requires a policy session.
High-range EKs can be used with a HMAC session because they have the
userWithAuth attribute set and we are creating them with an empty
authorization value.

https://trustedcomputinggroup.org/resource/http-trustedcomputinggroup-org-wp-content-uploads-tcg-ek-credential-profile/
https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance/
https://trustedcomputinggroup.org/resource/registry/
2026-07-01 17:36:50 +02:00
Paul Meyer
4dd73ad924 core: trust SMBIOS credentials under Intel TDX
SMBIOS OEM strings are host-controlled and normally distrusted by PID1
in confidential VMs. Under TDX, however, the SMBIOS table (including
Type 11) is measured into RTMR0 by the firmware (TDVF), so a remote
verifier can detect host tampering with credentials delivered this
way. Accept them there, while keeping fw_cfg distrusted as those
items are not measured even on TDX.

This lets systemd-vmspawn deliver credentials to TDX guests via the
normal SMBIOS path, unlike SNP which requires the initrd cpio channel.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
2026-07-01 16:09:27 +02:00
Luca Boccassi
04f8927173 Add more shutdown timestamps and preserve via LUO (#42671)
Add more shutdown timestamps, export them via D-Bus/Varlink, use them in
`systemd-analyze time`, and preserve them across kexec via LUO. This is
useful to measure reboot performance with added measurement points and
more granular intervals.
2026-07-01 14:12:21 +01:00
Paul Meyer
0a9f7b5487 vmspawn: allow TDX guest to connect to host QGS
To query a TD quote, the TDX guest must connect to the Quote Generation
Service (QGS), a SGX enclave running on the host. We check if the
service is exposed via a well-known unix socket, then pass that socket
or a fallback well-known vsock address to QEMU.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
2026-07-01 14:36:45 +02:00
Paul Meyer
a78afc1616 vmspawn: add Intel TDX confidential VM support
Wire up --coco=tdx alongside the existing SEV-SNP path. TDX requires KVM
on x86_64, a raw TDVF firmware loaded via -bios (no pflash/NVRAM split),
kernel-irqchip=split, and the "host" CPU model since QEMU rejects named
models. Sets up the tdx-guest object and confidential-guest-support=tdx0.

TDX measurement is different from QEMU's kernel-hashes injection: TDX
provides runtime measurements via RTMRs, so the initial measurement only
covers the firmware, which then measures the rest of the boot chain into
those RTMRs (done by OVMF today). Therefore a restriction to direct
kernel boot isn't required either.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
2026-07-01 14:35:25 +02:00
Davis-Rippon
fcb7cf86fe man: update description for sd_device_enumerator_add_match_subsystem
Signed-off-by: Davis-Rippon <drip0002@student.monash.edu>
2026-07-01 09:40:31 +01:00
Shihao Ren
bbb863a008 man: fix wrong KillUserProcesses= default in systemd-run(1)
systemd-run(1) hard-coded "the default" wording for KillUserProcesses=, but the
actual compile-time default is determined by the -Ddefault-kill-user-processes=
meson build option, which distributions set differently at packaging time.

Consistent with logind.conf(5).

Fixes: #42805

Signed-off-by: Shihao Ren <renshihao.rsh@gmail.com>
2026-06-30 13:30:32 +01:00
Luca Boccassi
3a79aaea83 analyze: use shutdown timestamps in time verb
[root@fedora ~]# systemd-analyze
 Startup finished in 486ms (stopping) + 48ms (exit) + 116ms (systemd-shutdown) + 774ms (kernel) + 1.939s (initrd) + 3.878s (userspace) = 7.243s
 graphical.target reached after 3.876s in userspace.
2026-06-30 10:21:18 +01:00
Luca Boccassi
0220732dba core: publish shutdown timestamps via D-Bus 2026-06-30 10:21:18 +01:00
dongshengyuan
b0d48e096c man: document that $XDG_CONFIG_HOME affects environment.d lookup path
Align the documentation with the actual behavior: if $XDG_CONFIG_HOME is
set to an absolute path in the user service manager environment, it takes
precedence over the default ~/.config/ when locating environment.d files.
Also note the bootstrapping limitation that variables defined inside
environment.d files are not yet available when the generator runs.

Fixes: #42777
Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
2026-06-30 09:00:11 +02:00
Lennart Poettering
339dcb2af2 cryptenroll: add interactive mode and Varlink IPC API (#42380)
Replaces: #31096
Fixes: #36298
2026-06-28 08:47:27 +02:00