]> git.ipfire.org Git - thirdparty/systemd.git/log
thirdparty/systemd.git
2 days agoci/mkosi: add postmarketos job 39823/head
Yu Watanabe [Sun, 28 Sep 2025 08:02:19 +0000 (17:02 +0900)] 
ci/mkosi: add postmarketos job

Currently, TEST-92-TPM2-SWTPM is skipped as it requires the following:
https://github.com/systemd/systemd/pull/42760
https://gitlab.alpinelinux.org/alpine/aports/-/work_items/18293

2 days agomkosi: add postmarketos support
Yu Watanabe [Sun, 14 Sep 2025 03:16:03 +0000 (12:16 +0900)] 
mkosi: add postmarketos support

postmarketOS image can be built with for example the following mkosi.local.conf:
```
[Distribution]
Distribution=postmarketos

[Output]
Format=disk

[Build]
UseSubvolumes=yes

[Runtime]
Firmware=uefi
```

2 days agohwdb: add touchpad toggle mapping for MSI Katana GF66 12UD
dirhamtriyadi [Fri, 26 Jun 2026 14:20:20 +0000 (21:20 +0700)] 
hwdb: add touchpad toggle mapping for MSI Katana GF66 12UD

2 days agoman: fix first argument in Environment= expansion example
Wang Yu [Fri, 26 Jun 2026 04:07:12 +0000 (12:07 +0800)] 
man: fix first argument in Environment= expansion example

The example states that the first /bin/echo invocation (using ${ONE})
receives the argument 'one' (with literal single quotes). However,
Environment=ONE='one' strips the syntactic single quotes during
unquoting — see systemd.syntax(7), "Quotes themselves are removed" —
so ONE holds the value one, and ${ONE} (exact-value substitution,
always a single argument) yields the argument one without quotes.

Fixes #42442

Signed-off-by: Wang Yu <wangyu@uniontech.com>
2 days agohwbd: correctly map Bluetooth Key on MSI Modern 15 H AI C1MG laptop
Fede2782 [Fri, 26 Jun 2026 08:06:26 +0000 (10:06 +0200)] 
hwbd: correctly map Bluetooth Key on MSI Modern 15 H AI C1MG laptop

Previously the key was unknown so add the correct mapping as it does not follow the general
case for MSI Laptops.

  [  192.562000] atkbd serio0: Unknown key released (translated set 2, code 0xd7 on isa0060/serio0).
  [  192.562011] atkbd serio0: Use 'setkeycodes e057 <keycode>' to make it known.

Add it currently as a definition specific for this model but can be generalized to other MSI
Laptops if this issue is present also elsewhere.

2 days agotmpfiles: do not fail when trying to apply ACL during mkosi build
Luca Boccassi [Mon, 22 Jun 2026 21:26:17 +0000 (22:26 +0100)] 
tmpfiles: do not fail when trying to apply ACL during mkosi build

When running in a mkosi namespaced env tmpfiles fails to set ACLs:

Running create action for entry a /buildroot/var/log/journal
Setting access ACL u::rwx,g::r-x,g:adm:r-x,m::r-x,o::r-x on /buildroot/var/log/journal
Setting access ACL "u::rwx,g::r-x,g:adm:r-x,m::r-x,o::r-x" on /buildroot/var/log/journal failed: Invalid argument

If EINVAL is returned and we are in a chroot, skip gracefully via
EOPNOTSUPP. The ACLs will be set on first boot.

3 days agopcrlock: reject device path node shorter than its header
Syed Mohammed Nayyar [Thu, 25 Jun 2026 16:46:03 +0000 (22:16 +0530)] 
pcrlock: reject device path node shorter than its header

event_log_record_extract_firmware_description() walks the device path
of a UEFI_IMAGE_LOAD_EVENT taken from the firmware TPM2 measurement log.
The per-node loop checks the remaining bytes against the node and its
declared length, but never that dp->length covers the 4-byte node header
offsetof(packed_EFI_DEVICE_PATH, path).

For a Media/File-Path node with length 3, the file-name extraction
computes dp->length - offsetof(packed_EFI_DEVICE_PATH, path) == 3 - 4,
which wraps to SIZE_MAX. utf16_to_utf8() treats SIZE_MAX as unbounded
and runs char16_strlen() over dp->path, reading past the log buffer; a
length of 0 also leaves dp non-advancing.

efi_get_boot_option() in src/shared/efi-api.c already rejects such nodes
with "if (dpath->length < 4) break;"; do the same here.

3 days agojournald-remote/gateway hardening fixes flagged by kres (#42733)
Lennart Poettering [Thu, 25 Jun 2026 20:09:58 +0000 (22:09 +0200)] 
journald-remote/gateway hardening fixes flagged by kres (#42733)

3 days agovmspawn: deliver credentials via initrd cpio under SEV-SNP (#42272)
Lennart Poettering [Thu, 25 Jun 2026 20:08:08 +0000 (22:08 +0200)] 
vmspawn: deliver credentials via initrd cpio under SEV-SNP (#42272)

Re-enables `--set-credential=` / `--load-credential=` under
`--coco=sev-snp` by packaging credentials into a cpio appended to the
initrd, mirroring what `systemd-stub` does for ESP-sourced credentials.
The initrd is covered by the launch measurement via `kernel-hashes=on`,
so the credentials are too.

Tested end-to-end on an SNP-capable host: credentials passed via
`--set-credential=` land in `/run/credentials/@encrypted/` inside the
guest.

3 days agonss-resolve: fix blank array checks and improve NSS status codes
dongshengyuan [Tue, 16 Jun 2026 01:19:15 +0000 (09:19 +0800)] 
nss-resolve: fix blank array checks and improve NSS status codes

Use sd_json_variant_is_blank_array() instead of is_blank_object() for
p.addresses and p.names, which are declared as JSON arrays. The wrong
predicate never triggered, allowing empty arrays to bypass the guards:
for p.names this caused a size_t underflow leading to an out-of-bounds
heap write; for p.addresses it returned success with no addresses.

Add explicit n_addresses == 0 guards after the family-filter loops so
entries with unsupported families also return NOTFOUND rather than
crashing on a NULL dereference.

In gethostbyname3_r (family-specific entry point), return NO_DATA for
all zero-address results — both blank array and all-filtered — since
both mean "name resolved, no record of the requested family". Keep
HOST_NOT_FOUND in gethostbyname4_r (both-families) where a blank or
all-unsupported result genuinely means the name was not found.

Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
Co-developed-by: Claude Opus 4.8 <noreply@anthropic.com>
3 days agojournal: Prevent total log loss on unclean shutdown at high write rates (#42639)
Yu Watanabe [Thu, 25 Jun 2026 17:49:59 +0000 (02:49 +0900)] 
journal: Prevent total log loss on unclean shutdown at high write rates (#42639)

In Meta production we have been considering using journald more widely
for some time. One of the blockers to doing that which I have noticed is
that often journald seems to have vastly less data after lockups/power
failures compared to plain files, which is not great when debugging
outages.

On small write rates this tends to be hard to reproduce, but when
writing thousands of messages a second, an unclean shutdown can result
in the end result being an active journal file with a header that
records an arena larger than the data that actually reached disk. What
happens is then that journalctl then discards the entire file(!),
completely ignoring that there is a huge amount of data which is
actually perfectly readable.

The reason for that is that the journal header is updated on every
append, while the file size and newly written arena contents are only
made durable on the filesystem's own schedule. After a crash, the header
can therefore describe writes which were logically completed by journald
but whose backing data or file metadata never reached disk.

Take the following example of how this can happen at high log rates:

1. journald appends objects into an mmap()ed arena, periodically growing
the file with fallocate() in FILE_SIZE_INCREASE (8M) steps and advancing
the header's arena_size tail pointers as it goes along.
2. The header is dirtied on every append, and its arena_size is advanced
at each fallocate(). It is, from the kernel's perspective, an ordinary
data page and is only made durable by the kernel's periodic page cache
writeback on its own schedule. The file's length, by contrast, is
metadata, made durable only when the filesystem commits a transaction
(or on an fsync(), which journald does not issue between sync
intervals).
3. journald marks journals NOCOW, so the header's data block is
overwritten in place and is decoupled from the size metadata. Nothing
orders the two with respect to each other. Writeback therefore can
routinely persist a header whose arena_size has run ahead of the file
length recorded on disk.
4. Power is lost. On the next boot the persisted header reflects an
arena_size and tail pointers which have been advanced for appends.
However their payload and the file metadata were never committed, so
header_size + arena_size now points well past the end of the file as it
exists on disk.
5. journal_file_verify_header() then rejects this with -ENODATA:

if (... || header_size + arena_size > (uint64_t) f->last_stat.st_size)
            return -ENODATA;

That is correct when opening for writing, because we must not append to
a file whose recorded state we cannot trust, and the caller must rotate
it away. But the same check also runs on read only opens, where it is
actively harmful. In the case of journalctl, the entire file is skipped,
even though the data hash table, the field hash table, and the head of
the array all are present and fully intact, and the great majority of
entries are physically present. In fact, only a very small part of the
most recently written tail is missing, but everything before is
readable. This results in mistakenly rejecting the entire file as
corrupt.

This happens extremely frequently on machines with high write rates
during power cuts or lockups. In testing writing ~7500 msg/s through
journald and then cutting power, I reproduced it in ten out of ten
attempts across different machines.

In each case, the header was left claiming ~296M of arena while only
~192-208M had reached disk. In this case, journalctl reports that it has
recovered 0 of ~335000 messages. Whether a given crash trips the
condition depends on where it falls relative to the header's writeback,
but when it does, the loss today is total. After this patch the vast
majority of messages can be retrieved.

Let's fix this by keeping the rejection for writing, but for read-only
opens, let's just clamp the arena to the real file size and skip the
consistency checks on the now unreliable tail pointers. The reader will
walk the entry array chain from its intact head and stop at the
truncation point by the bounds check that already exists, so there's no
need to do any more than that there.

3 days agoanalyze: don't treat user-scope services as running as root in `security`
Shihao Ren [Thu, 25 Jun 2026 07:15:29 +0000 (15:15 +0800)] 
analyze: don't treat user-scope services as running as root in `security`

`systemd-analyze security --user foo.service` currently flags units
without `User=` as running as root. For user manager instances this is
impossible: per systemd.exec(5), switching user identity is not
permitted there, so the service always runs under the calling user's
UID.

Track the runtime scope inside SecurityInfo and short-circuit
security_info_runs_privileged() and assess_user() for
RUNTIME_SCOPE_USER, so that User=/DynamicUser=, SupplementaryGroups=
and RemoveIPC= are no longer marked as if the service ran as root in
both the bus-backed and --offline paths.

Fixes #40292

Signed-off-by: Shihao Ren <renshihao.rsh@bytedance.com>
3 days agounit-name: introduce "strict" mode for unit name mangling (#42638)
Lennart Poettering [Thu, 25 Jun 2026 15:18:55 +0000 (17:18 +0200)] 
unit-name: introduce "strict" mode for unit name mangling (#42638)

unit_name_mangle_with_suffix() is quite benevolent by default and allows
the unit to "transition" into a different unit type than what's
requested via its suffix argument. For example, calling
unit_name_mangle_with_suffix() with "/foo/bar" as a unit name and
".service" as a suffix would give you "foo-bar.mount", without any
warning or error.

This could then lead to a quite confusing errors in certain situations:
```
~# systemd-run --remain-after-exit --unit /foo/bar true
Failed to start transient service unit: Cannot set property RemainAfterExit, or unknown property.
```
Given we can't change the default behaviour of
unit_name_mangle_with_suffix() as some parts of systemd already depend
on its "benevolence" (like systemctl), let's introduce a new flag -
UNIT_NAME_MANGLE_STRICT - that checks if the mangled/resolved unit
name's suffix matches the requested one and errors out if not.

With the flag used throughout systemd-run's code, the error in the above
case is now a bit more clear:
```
~# build/systemd-run --remain-after-exit --unit /foo/bar true
Path "/foo/bar" resolves to unit type "mount", but "service" is expected as unit.
Failed to mangle unit name: Invalid argument
```
Resolves: #39996

3 days agoFix: network sysupdate (#42745)
Lennart Poettering [Thu, 25 Jun 2026 15:14:59 +0000 (17:14 +0200)] 
Fix: network sysupdate (#42745)

And also some simple and defensive wives

3 days agohomed: fix home_unlocking_finish reporting success as failure
dongshengyuan [Thu, 25 Jun 2026 03:30:25 +0000 (11:30 +0800)] 
homed: fix home_unlocking_finish reporting success as failure

In home_unlocking_finish(), the success path calls operation_result_unref()
with the local variable r and the uninitialized error object. If either
user_record_good_authentication() or home_save_record() fails (both are
logged as "ignoring"), r is left negative and the D-Bus caller receives
an error reply despite the home having been unlocked successfully.

This causes PAM to reject the session even though the home directory is
mounted and accessible.

Fix by passing 0 and NULL — consistent with every other success path in
the file (home_locking_finish(), home_activation_finish(), etc.).

Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
3 days agonetworkd/resolved hardening fixes flagged by kres (#42736)
Lennart Poettering [Thu, 25 Jun 2026 15:13:58 +0000 (17:13 +0200)] 
networkd/resolved hardening fixes flagged by kres (#42736)

3 days agotpm2: add SWTPM fallback test, fixes and hardening (#42722)
Lennart Poettering [Thu, 25 Jun 2026 15:13:03 +0000 (17:13 +0200)] 
tpm2: add SWTPM fallback test, fixes and hardening (#42722)

3 days agotest-journal: Test hash chain lookups when the tail is lost 42639/head
Chris Down [Thu, 18 Jun 2026 07:07:13 +0000 (16:07 +0900)] 
test-journal: Test hash chain lookups when the tail is lost

3 days agotest-journal: Test bisecting reads when missing per-data entry array
Chris Down [Wed, 17 Jun 2026 13:12:28 +0000 (21:12 +0800)] 
test-journal: Test bisecting reads when missing per-data entry array

3 days agotest-journal: Test recovery with header more recent than data
Chris Down [Wed, 17 Jun 2026 12:33:04 +0000 (20:33 +0800)] 
test-journal: Test recovery with header more recent than data

3 days agojournal: Tolerate lost tail hash chain nodes
Chris Down [Thu, 18 Jun 2026 07:07:04 +0000 (16:07 +0900)] 
journal: Tolerate lost tail hash chain nodes

The data and field hash table chains have the same problem the previous
commit fixed for entry array chains. New data and field objects are
linked at the tail of their hash bucket by patching the previous tail
object's next_hash_offset in place, so after a crash a persisted
predecessor (or the bucket head) can point at an object whose body never
reached disk.

journal_file_find_data_object_with_hash() and
journal_file_find_field_object_with_hash() walk those chains while
resolving matches, and on -EADDRNOTAVAIL/-EBADMSG from
journal_file_move_to_object() they simply return the error directly.
That propagates up to real_journal_next(), which discards the whole file
from the query.

Give those two lookups the same tolerance: on a read-only file, treat an
unreadable chain node as the end of the bucket chain.

3 days agojournal: Recover filtered journal queries after crash truncated writes
Chris Down [Wed, 17 Jun 2026 11:45:11 +0000 (19:45 +0800)] 
journal: Recover filtered journal queries after crash truncated writes

generic_array_get() which is used for the unfiltered iteration path in
the previous commit treats a chain pointer that resolves past the end of
the file as the end of the chain. In that case, moving to the missing
array object returns -EADDRNOTAVAIL (or -EBADMSG), and it either stops
(going downwards) or steps back to the previous array (going upwards).

However, generic_array_bisect(), which is used for filtered or seeking
reads does not. On -EADDRNOTAVAIL/-EBADMSG from
journal_file_move_to_object(), it instead returns the error directly to
the caller, which propagates out through
sd_journal_next()/sd_journal_previous() and aborts the query.

The per-data entry array chain has the same issue as the global one,
since n_entries and entry_array_offset are (re)written in place as
entries are linked, and thus after a crash they can reference more
arrays than actually reached the disk. That is to say in practical
terms, a journal recovered for reading by the previous commit could
nevertheless still drop matching entries from `journalctl FIELD=value`,
and a seqnum or time seek into the lost region could fail outright.

Let's give generic_array_bisect() the same tolerance generic_array_get()
already has. That is, when moving to an entry array object fails, treat
the chain as ending at the previous array. This means that the result
matches what generic_array_get() would yield for the same file.

3 days agojournal-remote: fix hostname double-free on request_meta() error paths 42733/head
Luca Boccassi [Wed, 24 Jun 2026 12:41:06 +0000 (13:41 +0100)] 
journal-remote: fix hostname double-free on request_meta() error paths

request_handler() owns the hostname var and passes it by value to
request_meta(), which hands it to source_new(), which stores it in
source->importer.name without copying. If build_accept_encoding()
then fails, the hostname var is freed, and then the caller's
_cleanup_free_ frees it a second time.

Follow-up for 9ff48d0982fcb97923955685fe9fa4e0e67cb238

3 days agojournal-gatewayd: fix signed overflow in n_skip handling
Luca Boccassi [Wed, 24 Jun 2026 12:39:33 +0000 (13:39 +0100)] 
journal-gatewayd: fix signed overflow in n_skip handling

request_reader_entries() negated m->n_skip in signed context before
casting to uint64_t, which is undefined behaviour for
n_skip == INT64_MIN.

Follow-up for 77ad3b93de65c27cc82dbccc7d336c3aff768c77
Follow-up for a7bfb9f76b96888d60b4f287f29dcbf758ba34c0

3 days agomkosi: update mkosi ref to f7762b71437227922a367bb89597843c77494ef9
Luca Boccassi [Thu, 25 Jun 2026 08:26:23 +0000 (09:26 +0100)] 
mkosi: update mkosi ref to f7762b71437227922a367bb89597843c77494ef9

f7762b7143 sandbox: Preserve net caps across user namespace before unsharing net
582eadee34 Revert "Put build history into the output directory"
5ef262bc53 action: don't fail if apk cannot be downloaded
bdd341ff9b Lock the package cache during package manager invocations
da49fe976c Put build history into the output directory
1c392f1918 tests: Use unique machine names
e4f4026e30 tests: Reduce VM RAM size
de41a5e03e Don't leak gpg-agent when signing with gpg
1bc5d61e1d ci: Pin openSUSE to second-to-last Tumbleweed snapshot
c4d565a009 test: Use the main build's snapshot for extension builds
718b06c866 tests: ignore masked units in check-and-shutdown
0dc5ecbc02 ci: enable postmarketOS in integration testing
d4c6761ad3 action: install apk to /usr/bin
9980f31309 mkosi-vm: add systemd-efistub to postmarketOS config
5640ace38f mkosi.conf: add grub to postmarketOS
6741b440c0 mkosi-initrd: add sulogin, device-mapper to postmarketOS initrd
c3575c035c mkosi-tools: add missing packages to postmarketOS tools tree
0774bc2498 mkosi-tools: add apk-tools to tools trees for Arch and OpenSuSE
| * bb87e48401 curl: Retry on failures
|/
41fea1dd8d dnf: Work around librepo rejecting valid repomd signatures cross-distro
647e3b610b dnf: Proper repository metadata signature requirement
46d907cce2 dnf: Don't skip unavailable repositories during makecache
a91e89c3b7 run_locale_gen: noop if output_format is confext
30329e401b tests: Make integration tests runnable locally
be549f04db config: Don't propagate $MKOSI_DNF when using a tools tree
42ed648981 build(deps): bump actions/upload-artifact from 7.0.0 to 7.0.1
fd5eedd62b build(deps): bump aws-actions/configure-aws-credentials
86733c703d tree: check for root when copying SELinux attributes as well
de2256f8fe Skip security.ima xattrs when copying tree as non-root
| * 08ebf6d678 vmspawn: Exclude secure-boot unless requested
|/
1d3c51e36d obs workflow: do not build aarch64/i586

3 days agohomectl: retry DeactivateHome on transient busy errors
Luca Boccassi [Fri, 8 May 2026 13:21:33 +0000 (14:21 +0100)] 
homectl: retry DeactivateHome on transient busy errors

When 'homectl deactivate' is called immediately after a preceding
operation, the umount inside systemd-homework can fail with EBUSY
because something briefly holds a reference to the home mount (e.g. a
concurrent inspect). systemd-homed already handles this gracefully
by moving the home into the 'lingering' state and retrying deactivation
after 15 seconds, but the bus reply for the original DeactivateHome
call returns the org.freedesktop.home1.HomeBusy error immediately,
which makes TEST-46-HOMED flaky.

Fix homectl to follow homed and retry for up to 30 seconds on HomeBusy
and add a test case trying to make the issue more reproducible.

3 days agoshared/tpm2-util: use a define instead of a const static variable
Zbigniew Jędrzejewski-Szmek [Thu, 25 Jun 2026 08:59:28 +0000 (10:59 +0200)] 
shared/tpm2-util: use a define instead of a const static variable

Let's do the standard thing. The 'static const' variable requires space
and less efficient code (moving from memory instead of a const insertion).
This doesn't matter much, but let's follow the standard pattern.

Follow-up for 93e9c2c974f13a189524bf12d0e3a921431090fa.

3 days agoFix: core fixes (#42744)
Zbigniew Jędrzejewski-Szmek [Thu, 25 Jun 2026 12:39:53 +0000 (14:39 +0200)] 
Fix: core fixes (#42744)

Some simple code fixes

3 days agoCouple of hardening changes for utils flagged by kres (#42732)
Zbigniew Jędrzejewski-Szmek [Thu, 25 Jun 2026 12:31:35 +0000 (14:31 +0200)] 
Couple of hardening changes for utils flagged by kres (#42732)

3 days agotpm2: re-manufacture software TPM when state dir is incomplete 42722/head
Paul Meyer [Tue, 23 Jun 2026 14:07:34 +0000 (16:07 +0200)] 
tpm2: re-manufacture software TPM when state dir is incomplete

setup_swtpm() decided whether a software TPM had already been
manufactured by checking whether the state directory was empty. But
manufacture_swtpm() writes swtpm's config files before forking
swtpm_setup, so an interrupted manufacture leaves the directory
non-empty yet without a usable TPM. The next boot then mistook it for a
complete TPM and started swtpm against a broken state directory.

Keying off a swtpm state file like tpm2-00.permall is no better, as
swtpm_setup gives no guarantee any single one is written atomically or
last. Instead, have manufacture_swtpm() write a marker (.manufactured)
as its very last step, once swtpm_setup has exited successfully, and
gate on it: re-manufacture when it is missing in the initrd, and refuse
rather than start a broken TPM outside it.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
3 days agotpm2: write swtpm config files atomically via the state directory fd
Paul Meyer [Wed, 24 Jun 2026 06:58:10 +0000 (08:58 +0200)] 
tpm2: write swtpm config files atomically via the state directory fd

Open the swtpm state directory once and write the three config files
relative to that fd with WRITE_STRING_FILE_ATOMIC, rather than by path
with a plain truncating write. Writing atomically ensures a crash or a
concurrent reader never observes a half-written config file, and
operating through a single directory fd lets later steps reuse it.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
3 days agofileio: add write_string_filef_at()
Paul Meyer [Thu, 25 Jun 2026 11:27:21 +0000 (13:27 +0200)] 
fileio: add write_string_filef_at()

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
3 days agoTranslations update from Fedora Weblate (#42749)
Luca Boccassi [Thu, 25 Jun 2026 11:16:52 +0000 (12:16 +0100)] 
Translations update from Fedora Weblate (#42749)

Translations update from [Fedora
Weblate](https://translate.fedoraproject.org) for
[systemd/main](https://translate.fedoraproject.org/projects/systemd/main/).

Current translation status:

![Weblate translation
status](https://translate.fedoraproject.org/widget/systemd/main/horizontal-auto.svg)

3 days agounit-name: introduce "strict" mode for unit name mangling 42638/head
Frantisek Sumsal [Wed, 17 Jun 2026 12:09:43 +0000 (14:09 +0200)] 
unit-name: introduce "strict" mode for unit name mangling

unit_name_mangle_with_suffix() is quite benevolent by default and allows
the unit to "transition" into a different unit type than what's
requested via its suffix argument. For example, calling
unit_name_mangle_with_suffix() with "/foo/bar" as a unit name and
".service" as a suffix would give you "foo-bar.mount", without any
warning or error.

This could then lead to a quite confusing errors in certain situations:

~# systemd-run --remain-after-exit --unit /foo/bar true
Failed to start transient service unit: Cannot set property RemainAfterExit, or unknown property.

Given we can't change the default behaviour of
unit_name_mangle_with_suffix() as some parts of systemd already depend
on its "benevolence" (like systemctl), let's introduce a new flag -
UNIT_NAME_MANGLE_STRICT - that checks if the mangled/resolved unit
name's suffix matches the requested one and errors out if not.

With the flag used throughout systemd-run's code, the error in the above
case is now a bit more clear:

~# build/systemd-run --remain-after-exit --unit /foo/bar true
Path "/foo/bar" resolves to unit type "mount", but "service" is expected as unit.
Failed to mangle unit name: Invalid argument

Resolves: #39996

3 days agopo: Translated using Weblate (Spanish) 42749/head
Fco. Javier F. Serrador [Thu, 25 Jun 2026 10:17:55 +0000 (10:17 +0000)] 
po: Translated using Weblate (Spanish)

Currently translated at 100.0% (286 of 286 strings)

Co-authored-by: Fco. Javier F. Serrador <fserrador@gmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/es/
Translation: systemd/main

3 days agopo: Translated using Weblate (Romanian)
Weblate Translation Memory [Thu, 25 Jun 2026 10:17:55 +0000 (10:17 +0000)] 
po: Translated using Weblate (Romanian)

Currently translated at 89.5% (256 of 286 strings)

Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/ro/
Translation: systemd/main

3 days agopo: Translated using Weblate (Romanian)
Petru Rebeja [Thu, 25 Jun 2026 10:17:54 +0000 (10:17 +0000)] 
po: Translated using Weblate (Romanian)

Currently translated at 89.5% (256 of 286 strings)

Co-authored-by: Petru Rebeja <petru@rebeja.eu>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/ro/
Translation: systemd/main

3 days agomachined: allow privileged users to register other users machines (#39042)
Luca Boccassi [Thu, 25 Jun 2026 09:53:04 +0000 (10:53 +0100)] 
machined: allow privileged users to register other users machines (#39042)

Requires https://github.com/polkit-org/polkit/pull/591

3 days agomachined: allow privileged users to register other users machines 39042/head
Luca Boccassi [Fri, 19 Sep 2025 23:49:42 +0000 (00:49 +0100)] 
machined: allow privileged users to register other users machines

If a user is authenticated by polkit as admin then it should be
able to manage any resource on the system.

Follow-up for 119d332d9c2cf1974b235c8d9e4e3ad821cf436a

3 days agopolkit: check if user authenticated as admin
Luca Boccassi [Fri, 19 Sep 2025 23:49:00 +0000 (00:49 +0100)] 
polkit: check if user authenticated as admin

The new polkit will return a new detail regarding a successful
authentication: the actual result type, which we can use to
see whether the user authenticated as admin. This can be used
to grant additional privileges.

3 days agounits: harden systemd-report-sign-plain@.service
Paul Meyer [Wed, 24 Jun 2026 10:43:40 +0000 (12:43 +0200)] 
units: harden systemd-report-sign-plain@.service

Apply sandboxing. The plain backend's needs writable StateDirectory and
/dev/urandom for key generation. The service must stay root (the
private key is root-only), but everything else is locked down.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
3 days agojournald: bound field length in extra-fields reader
Syed Mohammed Nayyar [Wed, 24 Jun 2026 12:59:35 +0000 (18:29 +0530)] 
journald: bound field length in extra-fields reader

client_context_read_extra_fields() reads a 64-bit field length v from
the per-unit log-extra-fields file. n = sizeof(uint64_t) + v overflows
when v is near UINT64_MAX, so the "left < n" check is bypassed and the
following memchr() scans v bytes past the buffer. Bound v against the
remaining bytes instead, which cannot overflow.

3 days agounit-name: use FLAGS_SET() more
Frantisek Sumsal [Wed, 17 Jun 2026 12:09:19 +0000 (14:09 +0200)] 
unit-name: use FLAGS_SET() more

3 days agouid-range: fix out-of-bounds write in uid_range_partition() 42732/head
Luca Boccassi [Wed, 24 Jun 2026 12:56:37 +0000 (13:56 +0100)] 
uid-range: fix out-of-bounds write in uid_range_partition()

uid_range_partition() filled the grown entries[] buffer backwards in
place. The backward-fill invariant (the write cursor stays above the
read index) only holds when every source entry contributes at least
one partition; an entry with nr < size contributes zero, so the cursor
stalls while the read index keeps descending. A later multi-part
entry's writes then overwrite the still-live zero-part slot, the
corrupted slot is re-read as a one-part entry, and the next
range->entries[--t] underflows.

Add a forward compaction first pass that drops the zero-part entries
before the backward fill.

Follow-up for 025439faaa8c053fab9fd01fb5f45fb819408bc5

Co-Authored-by: Paul Meyer <katexochen0@gmail.com>
3 days agocore: derive restrict-fsaccess initramfs_s_dev offset from skeleton (#42705)
Zbigniew Jędrzejewski-Szmek [Thu, 25 Jun 2026 09:24:28 +0000 (11:24 +0200)] 
core: derive restrict-fsaccess initramfs_s_dev offset from skeleton (#42705)

Fixes #42689.

3 days agodhcp6: reject IA_PD_PREFIX with invalid prefix length 42736/head
Luca Boccassi [Wed, 24 Jun 2026 12:20:56 +0000 (13:20 +0100)] 
dhcp6: reject IA_PD_PREFIX with invalid prefix length

dhcp6_option_parse_ia_pdprefix() validates the lifetimes but never the
prefixlen byte, so a delegated prefix with prefixlen == 0 or > 128 is
stored in the lease and handed over.

RFC 8415 defines the prefix length as 1 to 128, and the send-side
option_append_pd_prefix() already rejects 0, so reject the out-of-range
values on the receive path too.

Follow-up for f8ad4dd45d761d839de49ddff9d7fbf46892c148

3 days agosd-lldp-rx: keep object ref around event callbacks
Luca Boccassi [Wed, 24 Jun 2026 12:53:07 +0000 (13:53 +0100)] 
sd-lldp-rx: keep object ref around event callbacks

If the user callback set via sd_lldp_rx_set_callback() drops the last
reference to the sd_lldp_rx object, trying to use it later does not go
well. Take a ref to keep the objects alive as long as they are needed.

3 days agosystemctl: fix continue placement in clean-or-freeze error handling 42744/head
dongshengyuan [Thu, 25 Jun 2026 08:40:28 +0000 (16:40 +0800)] 
systemctl: fix continue placement in clean-or-freeze error handling

When sd_bus_call() fails, the continue was inside the
'if (ret == EXIT_SUCCESS)' guard, so only the first failure skipped
adding the unit to the job waiter. On the second and subsequent
failures, the unit was still passed to bus_wait_for_units_add_unit()
despite no job being started, causing bus_wait_for_units_run() to
hang indefinitely.

Move continue outside the guard so any failure skips the waiter
registration. The guard still prevents ret from being overwritten by
a later error code.

Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
3 days agobasic: add assert() when doing pointer deref
Michael Vogt [Tue, 23 Jun 2026 15:34:18 +0000 (17:34 +0200)] 
basic: add assert() when doing pointer deref

Lennart reminded me in [1] that we need to add assert() in functions
that do pointer access. For the simple `*p` pointer dereferences
we even have an automatic coccinelle script that ensures that as
part of the automatic code checks.

However for deref in the `p->` style this is not supported right
now and adding it to coccinelle is hard because its too slow for
this kind of check. So I created a (slightly messy) tree-sitter
python script to see how many asserts we are currently missing.

This commit is the result of running it over the `src/basic`
dir and fixing the flagged issues. I plan to tidy it up and
add it to the checks too but this is orthogonal to this commit.

[1] https://github.com/systemd/systemd/pull/42360#discussion_r3426964562

3 days agocore: fix fd leak in exec_shared_runtime_deserialize_one
dongshengyuan [Thu, 25 Jun 2026 08:40:05 +0000 (16:40 +0800)] 
core: fix fd leak in exec_shared_runtime_deserialize_one

The userns/netns/ipcns fdpairs were declared as plain int arrays without
_cleanup_close_pair_. If exec_shared_runtime_add() fails (e.g. OOM on
hashmap_ensure_put), the already-opened fds are leaked.

Since exec_shared_runtime_add() uses TAKE_FD on success, the array
entries are reset to -1 after ownership transfer, so adding
_cleanup_close_pair_ is safe and closes the fds only when they were
never consumed.

Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
3 days agoAssorted coverity fixes (#42738)
Lennart Poettering [Thu, 25 Jun 2026 08:29:57 +0000 (10:29 +0200)] 
Assorted coverity fixes (#42738)

Coverity is back online, and it's not happy

3 days agonetwork: roll back ipv6ll_address on link_ipv6ll_gained() failure 42745/head
dongshengyuan [Thu, 25 Jun 2026 08:19:14 +0000 (16:19 +0800)] 
network: roll back ipv6ll_address on link_ipv6ll_gained() failure

If link_ipv6ll_gained() fails after ipv6ll_address is set, the address
remains non-null and the null-guard in address_update() never triggers
again, permanently suppressing SLAAC, DHCPv6 and RA on that link.

Clear ipv6ll_address on the failure path so the guard can fire when
the address is re-announced.

Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
3 days agosysupdate: propagate transfer_instance_vacuum() errors
dongshengyuan [Thu, 25 Jun 2026 08:16:40 +0000 (16:16 +0800)] 
sysupdate: propagate transfer_instance_vacuum() errors

Both vacuum loops silently return 0 on failure instead of propagating
the error code, hiding disk cleanup failures from the caller.

Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
3 days agosd-journal: fix memzero size in data hash table setup
dongshengyuan [Thu, 25 Jun 2026 08:01:42 +0000 (16:01 +0800)] 
sd-journal: fix memzero size in data hash table setup

journal_file_setup_data_hash_table() allocates s * sizeof(HashItem)
bytes for the hash table but then only zeroes s bytes, leaving 15/16 of
the entries uninitialized. This corrupts the hash chain in any newly
created journal file.

The adjacent journal_file_setup_field_hash_table() already uses the
correct size.

Signed-off-by: dongshengyuan <dongshengyuan@uniontech.com>
4 days agounits: harden systemd-tpm2-swtpm.service
Paul Meyer [Wed, 17 Jun 2026 16:03:55 +0000 (18:03 +0200)] 
units: harden systemd-tpm2-swtpm.service

Lock down the software TPM service: restrict the runtime directory (which
holds the AES key sealing swtpm's state) to 0700, and apply the usual
sandboxing (NoNewPrivileges, MemoryDenyWriteExecute, ProtectSystem-adjacent
Protect*/Restrict* knobs, PrivateNetwork, PrivateTmp, a @system-service
syscall filter, etc.).

A few common knobs can't be used here: the service must keep CAP_SYS_ADMIN
(needed for the ioctl that creates the vtpm proxy device on /dev/vtpmx),
and it needs runtime access to the ESP and its backing block device at a
path only known at runtime, which rules out PrivateDevices=, DevicePolicy=,
ProtectSystem= and User=/DynamicUser=.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
4 days agotpm2: stop the software TPM before the ESP is unmounted on shutdown
Paul Meyer [Tue, 23 Jun 2026 12:46:24 +0000 (14:46 +0200)] 
tpm2: stop the software TPM before the ESP is unmounted on shutdown

swtpm keeps its state on the ESP (--tpmstate=dir=) and thus holds it
busy for as long as it runs, but nothing ensured it was stopped before
the ESP was unmounted on shutdown, leaving boot.mount failing to
unmount.

Two things were missing:

- systemd-tpm2-swtpm.service has DefaultDependencies=no, which strips
  the implicit shutdown.target membership, so it was torn down late
  rather than stopped in an ordered manner. Add
  Conflicts=/Before=shutdown.target, as the sibling
  systemd-tpm2-setup{,-early}.service units already do.

- The generator only ordered the service
  After=boot.automount/efi.automount. Ordering after the .automount
  units is enough for start-up, but only an ordering against the actual
  .mount units makes the service stop (releasing the ESP) before the
  file system is unmounted. Add boot.mount/efi.mount to the After= line;
  this is a no-op at start-up, as the mount has no job of its own there
  (it is triggered on access via the automount).

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
4 days agotest: add TEST-92-TPM2-SWTPM for the software TPM fallback
Paul Meyer [Tue, 23 Jun 2026 12:40:51 +0000 (14:40 +0200)] 
test: add TEST-92-TPM2-SWTPM for the software TPM fallback

Boot a VM in EFI mode without a hardware/firmware TPM and with
systemd.tpm2_software_fallback=yes, so systemd-tpm2-generator manufactures a
software TPM on the ESP in the initrd and chainloads swtpm. Assert the service
starts, the vtpm-proxy device shows up, and a systemd-creds TPM2 seal/unseal
round-trip works. Then reboot and confirm the sealed secret still unseals,
i.e. the TPM state persisted on the ESP across the reboot.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
4 days agosd-future: drop redundant branch in test reader fiber 42738/head
Luca Boccassi [Wed, 24 Jun 2026 18:09:36 +0000 (19:09 +0100)] 
sd-future: drop redundant branch in test reader fiber

Both the error and the success path returned (int) n, so the check was
a no-op. Return the value directly.

CID#1660095

Follow-up for 7bc793e21f2d4bf67bd311545270bc515fe63ad9

4 days agocore: actually sort the parsed LUO session list
Luca Boccassi [Wed, 24 Jun 2026 18:07:56 +0000 (19:07 +0100)] 
core: actually sort the parsed LUO session list

The strv_sort() call sat after a for (;;) loop whose only exits are
return statements inside the loop, so it never ran.

CID#1660125

Follow-up for 82b8615463c306f8f7eeaec13600c89a7bbef151

4 days agodhcp-message-dump: guard against negative option type before indexing
Luca Boccassi [Wed, 24 Jun 2026 18:02:06 +0000 (19:02 +0100)] 
dhcp-message-dump: guard against negative option type before indexing

dhcp_option_type_from_code() returns _DHCP_OPTION_TYPE_INVALID (-EINVAL)
for the PAD and END option codes, and dump_dhcp_option_one() uses the
returned value directly as an index into the functions[] table. Those
codes are excluded by an assert() at the top of the function, but
assert() compiles down to __builtin_unreachable() under NDEBUG, so a
negative array index read is reachable there (and trips static
analyzers). Bail out explicitly on the error return.

CID#1660105

Follow-up for 149adb2fdce0d9a40f9332ecb1a48a486fce5194

4 days agohostname-setup: avoid O(N^2) string building in wildcard substitution
Luca Boccassi [Wed, 24 Jun 2026 11:24:37 +0000 (12:24 +0100)] 
hostname-setup: avoid O(N^2) string building in wildcard substitution

Building the result one char at a time via strextendn() is O(N^2)
because each call rescans and reallocs the buffer. With lines up to
LONG_LINE_MAX this caused a timeout in fuzz-hostname-setup. Use
GREEDY_REALLOC_APPEND to make it linear.

Fixes https://github.com/systemd/systemd/issues/42713

4 days agoresolved: fix potential use-after-free when freeing DNS extra stub listeners
Luca Boccassi [Wed, 24 Jun 2026 12:43:14 +0000 (13:43 +0100)] 
resolved: fix potential use-after-free when freeing DNS extra stub listeners

dns_stub_listener_extra_free() frees the listener while DnsQuery and
DnsStream objects still keep pointers to it. On a reload the extra
listeners are freed before dns_stream_disconnect_all() and
dns_query_free() run, and dns_query_free() then dereferences those
pointers.

4 days agoresolved: avoid dangling hashmap entry on RegisterService failure
Luca Boccassi [Wed, 24 Jun 2026 12:54:05 +0000 (13:54 +0100)] 
resolved: avoid dangling hashmap entry on RegisterService failure

bus_method_register_service() inserted the DnssdRegisteredService into
m->dnssd_registered_services before assigning service->manager and
before the sd_bus_track_new()/sd_bus_track_add_sender() calls, so if
either failed, the destructor ran with service->manager still NULL,
so its guarded hashmap_remove() was skipped and the freed service was
left in the hashmap.

4 days agosysupdate: do a varlink callout to a ready when completing an update, and hook bootct...
Lennart Poettering [Wed, 24 Jun 2026 14:58:45 +0000 (16:58 +0200)] 
sysupdate: do a varlink callout to a ready when completing an update, and hook bootctl install, pcrlock and sysext refresh into it (#42365)

4 days agohwdb: map Brazilian ThinkPad T14 Gen 1 slash key to KEY_RO
LucasTavaresA [Wed, 24 Jun 2026 12:21:29 +0000 (09:21 -0300)] 
hwdb: map Brazilian ThinkPad T14 Gen 1 slash key to KEY_RO

On Lenovo ThinkPad T14 Gen 1 AMD model 20UES5TQ00 with the Brazilian
keyboard, the physical slash/question key reports as KEY_RIGHTCTRL.

This keyboard layout has no physical Right Ctrl key in that position. The
key after Space is AltGr, then PrtSc, then the slash/question key. Map the
AT keyboard scancode 0x9d to KEY_RO, matching the ABNT slash/question key
used by Brazilian keyboard layouts.

Verified with evtest:

Event: type 4 (EV_MSC), code 4 (MSC_SCAN), value 9d
Event: type 1 (EV_KEY), code 97 (KEY_RIGHTCTRL), value 1

After applying the hwdb mapping, the key reports as KEY_RO.

DMI: svnLENOVO:pn20UES5TQ00:pvrThinkPadT14Gen1
AT keyboard scancode: 0x9d

4 days agostring-util: check for short input in previous_ansi_sequence()
Luca Boccassi [Wed, 24 Jun 2026 12:46:04 +0000 (13:46 +0100)] 
string-util: check for short input in previous_ansi_sequence()

ellipsize_mem() scans backwards for ANSI escape sequences and calls
previous_ansi_sequence(s, t - s, ...) as t walks down toward s. When
t reaches s + 1 the helper is invoked with length == 1 and computes
'length - 2', which wraps to SIZE_MAX - 1.

Follow-up for cb558ab222f0dbda3afd985c2190f35693963ffa

4 days agoTODO: drop bootctl link + sysupdate integration item 42365/head
Lennart Poettering [Thu, 28 May 2026 09:42:57 +0000 (11:42 +0200)] 
TODO: drop bootctl link + sysupdate integration item

This is now implemented: sysupdate calls out to the
/run/systemd/sysupdate/notify/ Varlink directory on completion, and bootctl
binds a socket there that links a UKI plus extras staged below
/var/lib/systemd/uki/ (with .v/ vpick support) via "bootctl link-auto".

4 days agotest: verify bootctl link-auto and io.systemd.BootControl.LinkAuto
Lennart Poettering [Thu, 28 May 2026 10:20:59 +0000 (12:20 +0200)] 
test: verify bootctl link-auto and io.systemd.BootControl.LinkAuto

Add a TEST-87 testcase exercising "bootctl link-auto" and the equivalent
io.systemd.BootControl.LinkAuto() Varlink method: a UKI plus extras are staged
below the search directories and we assert the kernel and sidecar resources
are linked into $BOOT. Covered: plain kernel.efi + extras.d/, versioned
kernel.efi.v/ and extras .v/ resolved via vpick, directory priority
(/etc wins over /run), the no-op case when nothing is staged, and the Varlink
method including its empty reply when there is nothing to link.

4 days agotest: verify sysupdate invokes the notification callout directory
Lennart Poettering [Thu, 28 May 2026 09:42:57 +0000 (11:42 +0200)] 
test: verify sysupdate invokes the notification callout directory

Extend TEST-72-SYSUPDATE with a check that, after a successful update,
systemd-sysupdate connects to every socket linked into
/run/systemd/sysupdate/notify/ and invokes
io.systemd.SysUpdate.Notify.OnCompletedUpdate(). A tiny recorder socket is
hooked into that directory; it captures the request and replies with success.
We assert the recorded call carries the expected method, version and resource
list, and that a subsequent no-op update emits no notification.

4 days agosystemd-boot-update: condition on UEFI
Lennart Poettering [Fri, 29 May 2026 13:40:45 +0000 (15:40 +0200)] 
systemd-boot-update: condition on UEFI

Our boot loader logic only supports UEFI, hence let's condition the
updater on it.

4 days agosysext: refresh sysexts and confexts on completed system update
Lennart Poettering [Thu, 28 May 2026 09:42:47 +0000 (11:42 +0200)] 
sysext: refresh sysexts and confexts on completed system update

Bind the io.systemd.SysUpdate.Notify.OnCompletedUpdate() method in the
sysext Varlink server. systemd-sysext provides a single Varlink service
covering both the sysext and confext image classes, so one notification
refreshes both (equivalent to "systemd-sysext refresh" plus
"systemd-confext refresh"). Hook a socket into
/run/systemd/sysupdate/notify/ via systemd-sysupdate-notify-sysext.socket,
enabled by default via the preset.

4 days agobootctl: add link-auto/LinkAuto and auto-link on completed system update
Lennart Poettering [Thu, 28 May 2026 09:42:21 +0000 (11:42 +0200)] 
bootctl: add link-auto/LinkAuto and auto-link on completed system update

Add a "bootctl link-auto" verb and a matching io.systemd.BootControl.LinkAuto()
Varlink method that behave exactly like "bootctl link" / Link(), except that
the UKI and extra resources are discovered automatically instead of being
passed in. The following directories are searched, in decreasing priority:
/etc/systemd/uki/, /run/systemd/uki/, /var/lib/systemd/uki/ (where
systemd-sysupdate stages downloaded resources), /usr/local/lib/systemd/uki/
and /usr/lib/systemd/uki/.

  - the UKI is taken from kernel.efi, or the best version in kernel.efi.v/
    (resolved via vpick, without honouring boot-counting suffixes), from the
    highest-priority directory that has one;
  - extra resources are picked up from extras.d/, matching *.sysext.raw,
    *.confext.raw and *.cred, each either as a plain file or as a versioned
    *.v/ directory resolved via vpick, combined across all directories with
    higher-priority directories winning on conflicts.

Everything is resolved relative to the pinned root directory fd. Files passed
via --extra= on the command line are linked in addition to the auto-discovered
ones.

Also bind io.systemd.SysUpdate.Notify.OnCompletedUpdate() in the boot control
Varlink server, which simply does the same as LinkAuto(), and hook a socket
into /run/systemd/sysupdate/notify/ via systemd-sysupdate-notify-bootctl.socket
(enabled by default via the preset) so a freshly downloaded kernel is linked
into $BOOT automatically after a sysupdate run.

4 days agopcrlock: recompute PCR policy on completed system update
Lennart Poettering [Thu, 28 May 2026 09:41:45 +0000 (11:41 +0200)] 
pcrlock: recompute PCR policy on completed system update

Bind the io.systemd.SysUpdate.Notify.OnCompletedUpdate() method in the
pcrlock Varlink server and hook a socket into
/run/systemd/sysupdate/notify/ via systemd-sysupdate-notify-pcrlock.socket,
enabled by default via the preset. When sysupdate signals a completed
update, we unconditionally re-run make-policy, since the set of measured
components may have changed.

4 days agosysupdate: notify hook subscribers after a successful update
Lennart Poettering [Thu, 28 May 2026 09:40:42 +0000 (11:40 +0200)] 
sysupdate: notify hook subscribers after a successful update

Define a new io.systemd.SysUpdate.Notify Varlink interface with a single
OnCompletedUpdate() method, and after sysupdate successfully installs an
update, invoke that method on every socket linked into
/run/systemd/sysupdate/notify/ via varlink_execute_directory(). This
gives other components a hook to react to applied updates (e.g. recompute
a TPM policy, link a freshly downloaded kernel, refresh extensions).

The notification carries the component name, the installed version and the
list of updated resources (transfer id + on-disk path). Subscribers are
free to ignore the parameters and just treat the call as a trigger.

Setting SYSTEMD_SYSUPDATE_FORCE_NOTIFY=1 forces the notification to be sent
even when no update was applied (in which case no resource list is included),
so follow-up work can be triggered unconditionally.

Fixes: #35988
4 days agovpick: take separate root_fd and dir_fd arguments
Lennart Poettering [Thu, 28 May 2026 10:37:39 +0000 (12:37 +0200)] 
vpick: take separate root_fd and dir_fd arguments

Mirror how chaseat() works these days: instead of a single toplevel_fd that
serves as both the root (chroot) boundary and the directory that resolution
starts from, path_pick() now takes a separate root_fd and dir_fd. This lets
callers resolve a path relative to a specific directory fd while confining
symlink and absolute-path resolution to a root directory fd.

All existing callers are updated to pass the same fd for both, preserving
their current behaviour.

4 days agoman: document SEV-SNP credential delivery via initrd cpio 42272/head
Paul Meyer [Sat, 23 May 2026 15:37:40 +0000 (17:37 +0200)] 
man: document SEV-SNP credential delivery via initrd cpio

Under --coco=sev-snp, credentials no longer flow through SMBIOS/fw_cfg
(which the guest PID1 discards as unmeasured in confidential VMs) but
through a cpio archive appended to the initrd, landing in the @system
bucket via the new /.extra/system_credentials/ initrd path. Update
systemd-vmspawn(1) to describe this and the guest systemd version
requirement.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
4 days agovmspawn: deliver credentials via initrd cpio under SEV-SNP
Paul Meyer [Sat, 23 May 2026 15:05:56 +0000 (17:05 +0200)] 
vmspawn: deliver credentials via initrd cpio under SEV-SNP

Previously, --load-credential / --set-credential were rejected outright
under --coco=sev-snp because the SMBIOS type-11 transport isn't covered
by the launch measurement. PID1 wouldn't have accepted those credentials
anyway (import_credentials_smbios() refuses any SMBIOS-sourced credentials
under a confidential VM).

Instead, when SNP is in use and credentials are present, synthesize a
newc cpio archive containing each credential at
.extra/system_credentials/<id>.cred and append it to the initrd list.
The existing merge_initrds() path then concatenates it into the single
initrd file QEMU loads, which kernel-hashes=on covers in the SEV-SNP
launch digest. PID1's import_credentials_boot() picks them up from the
trusted /.extra/system_credentials/ path and routes them to the @system
bucket, so units can consume them via LoadCredential= unchanged.

Direct kernel boot (--linux=) is already required under SNP, so the
initrd is always under our control here. The cpio synthesis happens
after all internal machine_credential_add()/machine_credential_load()
call sites so the archive captures the complete credential set (journal
forwarding, vmm.notify_socket, ssh ephemeral keys, etc.).

The cpio path is intentionally scoped to SNP: it requires a guest PID1
that knows about /.extra/system_credentials/, and we don't want to
regress credential delivery for non-CoCo guests running older systemd
versions in the guest. Consider switching when the new path is widely
available.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
4 days agoshared: add userspace cpio writer for credentials
Paul Meyer [Sat, 23 May 2026 14:25:55 +0000 (16:25 +0200)] 
shared: add userspace cpio writer for credentials

Add a small newc-format cpio encoder that builds an archive with each
credential as a file under .extra/system_credentials/<id>.cred and
writes it to a temp file. This mirrors what systemd-stub produces from
ESP credentials, so PID1's import_credentials_boot() picks them up
unchanged via the new /.extra/system_credentials/ initrd path.

Motivated by vmspawn under SEV-SNP, where SMBIOS credentials aren't
covered by the launch measurement and are discarded by PID1 in
confidential guests, so they must be delivered via the measured initrd
instead. The writer lives in src/shared/ so other host-side tooling
can reuse it.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
4 days agocore: import trusted initrd credentials
Paul Meyer [Wed, 3 Jun 2026 11:23:27 +0000 (13:23 +0200)] 
core: import trusted initrd credentials

PID1's import_credentials_boot() so far always treated initrd-delivered
credentials as untrusted: anything found under /.extra/credentials/
was routed into ENCRYPTED_CREDENTIALS_DIRECTORY, forcing consumers to
use LoadCredentialEncrypted= and provide credentials in systemd-creds
encrypted form. That matches the trust model for stub which sources
credentials from the EFI System Partition (mountable and editable
offline).

Host-side producers that take responsibility for the trust of the cpio
they hand to the kernel have a different model: e.g. systemd-vmspawn
builds an initrd-credentials cpio whose bytes are covered by the SEV-SNP
launch measurement via QEMU's kernel-hashes=on (or, in non-confidential
setups, by the host itself being the trust root). Forcing those through
the @encrypted bucket would require null-key wrapping on the host and
LoadCredentialEncrypted= on the consumer side, a needless API split for
unit files that should otherwise be portable between confidential and
non-confidential boots.

Extend import_credentials_boot() to import credentials from
/.extra/system_credentials/, routed into SYSTEM_CREDENTIALS_DIRECTORY.
Consumers access these via LoadCredential= directly, with no
encrypted-credential ceremony.

The per-directory walk is hoisted into a small static helper so the new
target bucket can share the existing copy/validation logic; behavior
for the existing untrusted paths is unchanged.

Also set the new RECURSE_DIR_MUST_BE_REGULAR flag as a drive-by.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
4 days agounits: tag more units correctly with varlink xattrs
Lennart Poettering [Wed, 24 Jun 2026 06:24:05 +0000 (08:24 +0200)] 
units: tag more units correctly with varlink xattrs

These were added in parallel to #42454, hence catch up and add missing
xattrs.

Follow-up for 53fc4c48e7d40293e8f79392e2da91323dd50268

4 days agosysupdate: automatically clean up orphaned files after auto-update (#42714)
Lennart Poettering [Wed, 24 Jun 2026 10:29:50 +0000 (12:29 +0200)] 
sysupdate: automatically clean up orphaned files after auto-update (#42714)

This adds an operation equivalent to "systemd-sysupdate cleanup" after
an update completed (regardless if that update was entirely successful
or not). This ensures that any orphaned files are automatically cleaned
up, if they are not referenced by any transfer file's patterns anymore.

Follow-up for: d82e256bb9d151b185a8afec1fcacd8fbe80555c

4 days agopo: Translated using Weblate (Romanian)
Petru Rebeja [Wed, 24 Jun 2026 08:17:54 +0000 (08:17 +0000)] 
po: Translated using Weblate (Romanian)

Currently translated at 76.2% (218 of 286 strings)

Co-authored-by: Petru Rebeja <petru@rebeja.eu>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/ro/
Translation: systemd/main

4 days agosysupdate: automatically clean up orphaned files after auto-update 42714/head
Lennart Poettering [Tue, 23 Jun 2026 19:15:53 +0000 (21:15 +0200)] 
sysupdate: automatically clean up orphaned files after auto-update

This adds an operation equivalent to "systemd-sysupdate cleanup" after
an update completed (regardless if that update was entirely successful
or not).  This ensures that any orphaned files are automatically cleaned
up, if they are not referenced by any transfer file's patterns anymore.

Follow-up for: d82e256bb9d151b185a8afec1fcacd8fbe80555c

4 days agotest-execute: use per-Exec timeout instead of per-service timeout
Luca Boccassi [Tue, 23 Jun 2026 09:39:01 +0000 (10:39 +0100)] 
test-execute: use per-Exec timeout instead of per-service timeout

The previous x2 was still not enough, and the test is still killed often in
slow GHA CI workers, eg:

https://github.com/systemd/systemd/actions/runs/28012425459/job/82908555094?pr=42705

This happens in test units with many commands, so reset the timer when
a command completes and the test advances. The number of Exec
instructions is bounded so this will terminate jobs that are really
stuck anyway.

Follow-up for 3b00327fe6004b03c4a963de3df51998cf0c79b4

5 days agocore: pin restrict-fsaccess initramfs_s_dev store width to skeleton field 42705/head
tunaichao [Wed, 24 Jun 2026 06:01:06 +0000 (14:01 +0800)] 
core: pin restrict-fsaccess initramfs_s_dev store width to skeleton field

The clear-store in restrict_fsaccess_clear_initramfs_trust() writes a fixed
4 bytes (*(uint32_t *)(p + INITRAMFS_S_DEV_OFF) = 0). INITRAMFS_S_DEV_OFF is
derived from the skeleton, so the offset tracks any field widening, but the
store width does not: were initramfs_s_dev widened (e.g. __u32 -> __u64) in
the BPF program, the store would clear only the low 4 bytes and silently
leave the initramfs trust window partially open. That is exactly the class
of bug the mirror-struct asserts (removed earlier in this branch) guarded
against.

Add a compile-time assert pinning the store width to the skeleton field
width (sizeof_field(typeof_field(struct restrict_fsaccess_bpf, bss[0]),
initramfs_s_dev) == sizeof(uint32_t)), so widening the field fails the build
instead of clearing half of it.

5 days agocore: derive restrict-fsaccess initramfs_s_dev offset from skeleton
tunaichao [Tue, 23 Jun 2026 07:45:49 +0000 (15:45 +0800)] 
core: derive restrict-fsaccess initramfs_s_dev offset from skeleton

Building with -Dbpf=enabled -Dbpf_compiler=gcc (GCC's BPF backend) fails on
the static assertions in bpf-restrict-fsaccess.c, introduced in 68fe7fa4d6:

  error: static assertion failed:
  "offsetof(struct restrict_fsaccess_bss, initramfs_s_dev) ==
   offsetof(typeof_field(struct restrict_fsaccess_bpf, bss[0]), initramfs_s_dev)"

The hand-written struct restrict_fsaccess_bss lists the BPF .bss globals in
source declaration order and asserts that its layout matches the skeleton's
generated bss struct. bpftool gen skeleton emits that struct from the BTF
.bss DATASEC, whose member order reflects the physical order the compiler
placed the variables, not the source order. clang preserves declaration
order, so the asserts pass; gcc reorders .bss globals, so initramfs_s_dev no
longer sits at offset 0 and the asserts fail.

This is more than a build break: restrict_fsaccess_clear_initramfs_trust()
clears initramfs_s_dev by mmap()ing the .bss map and storing 0 at a hardcoded
offset 0. Under the gcc layout that store would clobber the wrong global,
silently leaving the initramfs trust window open after switch_root instead of
closing it. The asserts were correctly catching this.

Fix it by deriving the offset from the generated skeleton instead of a mirror
struct: drop struct restrict_fsaccess_bss and the four field-order
assert_cc()s, take INITRAMFS_S_DEV_OFF from the skeleton's bss struct
(offsetof(typeof_field(struct restrict_fsaccess_bpf, bss[0]),
initramfs_s_dev)), and store at p + INITRAMFS_S_DEV_OFF. The offset is a
compile-time constant, so clang (offset 0) is unchanged while gcc tracks the
real layout. A retained assert_cc() documents the 4-byte alignment the
single-store atomicity relies on.

Fixes: #42689
5 days agosd-varlink: mark varlink sockets via xattrs (#42454)
Lennart Poettering [Wed, 24 Jun 2026 04:16:39 +0000 (06:16 +0200)] 
sd-varlink: mark varlink sockets via xattrs (#42454)

Linux 7.0 added the ability to mark socket inodes with xattrs. Let's use
that to clearly mark all our Varlink sockets as being varlink related.
This is then used to implement a very useful new command "varlinkctl
list-sockets" which lists all varlink entrypoint sockets marked this
way.

By marking not just the entrypoint inodes but also the connection
sockets properly, we can one day add an ebpf based "varlinkctl trace"
command that watches varlink sockets for traffic. but that's material
for a later PR.

5 days agotest: skip fdstore tests if test-fdstore is not available
Frantisek Sumsal [Tue, 23 Jun 2026 19:29:53 +0000 (21:29 +0200)] 
test: skip fdstore tests if test-fdstore is not available

When the test suite is run in the "standalone" mode, the minimal
container might not contain the test-fdstore binary that's needed for a
couple of tests. Since installing systemd-tests into the minimal
container pulls in a lot of other dependencies, let's just skip the
affected tests instead to avoid this.

5 days agoupdate TODO 42454/head
Lennart Poettering [Wed, 3 Jun 2026 09:12:22 +0000 (11:12 +0200)] 
update TODO

5 days agoman: document sd_varlink_server_listen_address() and friends
Lennart Poettering [Wed, 3 Jun 2026 13:30:56 +0000 (15:30 +0200)] 
man: document sd_varlink_server_listen_address() and friends

5 days agotree-wide: relax access mode of private Varlink sockets a bit
Lennart Poettering [Wed, 3 Jun 2026 10:10:49 +0000 (12:10 +0200)] 
tree-wide: relax access mode of private Varlink sockets a bit

5 days agounits: tag all .varlink sockets with the right xattrs
Lennart Poettering [Wed, 3 Jun 2026 06:37:03 +0000 (08:37 +0200)] 
units: tag all .varlink sockets with the right xattrs

This also relaxes the inode access modes a bit, in case they were set to
0600: we now set the "r" bit too, i.e. use 0644. This is beneficial
since it permits unpriv code to read the xattrs of the entrypoints
(which require read access). Note that in order to be able to connect()
to a socket inode you need write access, hence this shouldn't compromise
security in any way.

5 days agovarlinkctl: add 'list-sockets' verb
Lennart Poettering [Tue, 2 Jun 2026 16:53:07 +0000 (18:53 +0200)] 
varlinkctl: add 'list-sockets' verb

5 days agosd-netlink: beef up sock-diag code a bit
Lennart Poettering [Tue, 2 Jun 2026 16:52:00 +0000 (18:52 +0200)] 
sd-netlink: beef up sock-diag code a bit

Let's make it useful to enumerate AF_UNIX sockets.

5 days agobpf-restrict-fsaccess: move STAT_DEV_TO_KERNEL into generic code
Lennart Poettering [Tue, 2 Jun 2026 16:51:13 +0000 (18:51 +0200)] 
bpf-restrict-fsaccess: move STAT_DEV_TO_KERNEL into generic code

We want to reuse it when processing sock-diag messages, hence let's
generalize this.

5 days agocore: add socket xattr settings for socket unit
Lennart Poettering [Tue, 2 Jun 2026 16:22:50 +0000 (18:22 +0200)] 
core: add socket xattr settings for socket unit

5 days agovarlinkctl: port to new help-util.[ch] apis
Lennart Poettering [Tue, 2 Jun 2026 15:49:00 +0000 (17:49 +0200)] 
varlinkctl: port to new help-util.[ch] apis

5 days agosd-varlink: mark varlink sockets and entrypoint inodes as varlink via xattrs
Lennart Poettering [Tue, 2 Jun 2026 15:36:52 +0000 (17:36 +0200)] 
sd-varlink: mark varlink sockets and entrypoint inodes as varlink via xattrs

5 days agosocket-util: add new helper socket_xattr_supported()
Lennart Poettering [Wed, 3 Jun 2026 09:06:23 +0000 (11:06 +0200)] 
socket-util: add new helper socket_xattr_supported()

5 days agoxattr-util: use empty_to_null() where appropriate
Lennart Poettering [Tue, 2 Jun 2026 15:35:49 +0000 (17:35 +0200)] 
xattr-util: use empty_to_null() where appropriate