Commit Graph
89094 Commits
Author SHA1 Message Date
Daan De Meyer 35bf1c8264 mkosi: update mkosi ref to 77fce77807a9a92bc37edc8f1c967102e6236d94
* 77fce77807 apk: Implement repository_key_fetch for the postmarketOS distribution
* 7068ed49ab postmarketos: Add ruff to tools tree
* dea4b6bfc8 Add newline when writing machine id into /etc/machine-id
* 944b775d40 tools: add libtss2-tcti-device0 to opensuse tools tree
* d856d65d3b mkosi-initrd: Also add cryptsetup-libs explicitly to the initrd
* 1cc967c5b3 mkosi-initrd: Trim orphaned GPU/audio modules, add ACPI platform attrs
* a3e95a7c29 mkosi-tools: Add fish to misc profile
* 76b02d1f84 mkosi-tools: Add jujutsu to misc profile
* 0afe4cd254 mkosi-tools: Move gh to misc profile
* 9077634bad mkosi-tools: Add cryptsetup-libs to centos/fedora/opensuse
* 82846347af box: Drop background tinting
* 3e50b97101 mkosi-tools: Add libfido2
* 78c2784827 vmspawn: Use --ephemeral rather than copy_ephemeral()
* dc801b00a3 Added second call to update kerneltype after kernel is defined
* 0c5cc04a8b vmspawn: Forward journal-remote settings to vmspawn
* 2518468c65 nspawn: Use --forward-journal instead of running journal-remote ourselves
* d2b798d00c apk: skip removal of packages that aren't installed
2026-05-19 20:16:25 +02:00
Frantisek Sumsal e7cd836dcf resolve: cap pre-allocation for questions/RRs
Since [0] and [1] questions & answer RRs from the incoming packets are
parsed into a hashmap to speed things up. The hashmaps are even
pre-allocated to speed things up even more, but there's one caveat - the
size for the pre-allocation comes from one or more fields from the
incoming packets that are under sender's control.

This can be abused by a malicious DNS server which can send a packet
with a spoofed QDCOUNT (for question packets) or ANCOUNT/NSCOUNT/ARCOUNT
(for answer packets). The limit of the final value in both cases is 64K.
This value is then used to pre-allocate the hashmap (via
set_reserve()/ordered_set_reserve(), where the caller also multiplies
the input value by 2 in both cases), which in turns calls
resize_buckets() that memzero()s the pre-allocated area, so all the
pages are faulted in, showing in process' RSS. Each such spoofed packet
then can translate into a ~4 MiB allocation in the systemd-resolved
process, which doesn't sound that bad.

However, this can be further amplified if the spoofed packet ends up in
resolved's cache. So, if the spoofed packet contains one valid A record
and then an OPT record with a spoofed ARCOUNT, the whole packet ends up
in the cache that can hold 4K of entries, which can eventually cause
resolved to keep up to 16 GiB of memory just for the cache (and thanks
to the memzero() above it's all RSS). Note that all this requires
someone with enough privileges to configure resolved to actually point
to such malicious DNS server or it could come from a malicious DHCP
server on the network. This could also get exploited via LLMNR, but in
thas case an attacker would have to match an ID of a valid transaction
for the packet to end up in resolved's cache.

For example, with a malicious DNS already in resolved configuration:

$ resolvectl dns eth0
Link 2 (eth0): 192.168.99.1:5354

Filling resolved's cache:

$ for i in {0..4200}; do resolvectl query test-$i.example.com; done
...
test-4200.example.com: 192.0.2.1               -- link: dummy0

-- Information acquired via protocol DNS in 1.6ms.
-- Data is authenticated: no; Data was acquired via local or encrypted transport: no
-- Data from: network

Yields following memory increase:

$ while :; do grep VmRSS /proc/$(pidof systemd-resolved)/status; sleep 1; done
VmRSS:     14280 kB
VmRSS:     14280 kB
...
VmRSS:    403352 kB
VmRSS:   1017976 kB
VmRSS:   1603876 kB
VmRSS:   2202028 kB
...
VmRSS:  16795724 kB
VmRSS:  16795724 kB

In my testing I also noticed one annoyance - after certain threshold the
RSS increase persisted even after the malicious entries were evicted
from the cache (or flushed via `resolvectl flush-caches`). This was most
likely due to mmap_threshold getting bumped to > 4 MiB and neither cache
eviction nor flush-caches call malloc_trim(0) (via
sd_event_trim_memory() or similar).

To mitigate this, let's cap the pre-allocation to a maximum number of
records the given packet body can realistically contain. If the minimum
size would be, for whatever unlikely reason, not enough, nothing serious
would happen - the hashmap would still get resized automatically by
resize_buckets(), it'd be just slightly slower.

[0] ae45e1a383
[1] 2d34cf0c16
2026-05-20 03:13:38 +09:00
Yu Watanabe 698b462409 systemd-coredump: add COREDUMP_CODE (#42019)
Add COREDUMP_CODE to the fields captured by systemd-coredump. This makes
it possible for system administrators to filter coredumps based on si_code,
which describes the reason why a given signal was sent.

For example, to find processes killed due to invalid permissions
(SEGV_ACCERR):

$ journalctl COREDUMP_SIGNAL=11 COREDUMP_CODE=2

I've decided to add the value of si_code to the 'Signal: ' line of
coredumpctl info:
    Signal: 11 (SEGV) si_code: SEGV_ACCERR
2026-05-20 03:10:40 +09:00
Nandakumar Raghavan f7e6645ac6 networkd: add RouteTable= to [DHCPv6] section
Allow users to allow DHCPv6 unreachable/blackhole routes (installed
for delegated prefixes) into a specific routing table, analogous to
the existing RouteTable= in [DHCPv4] and [IPv6AcceptRA].

The config parser config_parse_dhcp_or_ra_route_table() is extended
with an AF_UNSPEC ltype discriminator for DHCPv6 (AF_INET6 is already
taken by NDISC/RA). link_get_dhcp6_route_table() follows the same
pattern as link_get_dhcp4_route_table() and link_get_ndisc_route_table(),
falling back to the VRF table when not explicitly set.

In dhcp_request_unreachable_route(), the table is applied only for
NETWORK_CONFIG_SOURCE_DHCP6 routes (the uplink unreachable aggregates),
not DHCP_PD routes (per-subnet routes on downstream interfaces), matching
the intent of the feature. The !route->table_set guard avoids overriding
a table already set by the route code.
2026-05-20 03:03:33 +09:00
dependabot[bot] 94bbfd2a34 build(deps): bump the actions group with 2 updates
Bumps the actions group with 2 updates: [github/codeql-action](https://github.com/github/codeql-action) and [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials).


Updates `github/codeql-action` from 4.35.2 to 4.35.4
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/95e58e9a2cdfd71adc6e0353d5c52f41a045d225...68bde559dea0fdcac2102bfdf6230c5f70eb485e)

Updates `aws-actions/configure-aws-credentials` from 6.1.0 to 6.1.1
- [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases)
- [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md)
- [Commits](https://github.com/aws-actions/configure-aws-credentials/compare/ec61189d14ec14c8efccab744f656cffd0e33f37...d979d5b3a71173a29b74b5b88418bfda9437d885)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.35.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: aws-actions/configure-aws-credentials
  dependency-version: 6.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-20 02:39:05 +09:00
Luca Boccassi 15dc3c3f67 Translations update from Fedora Weblate (#42181)
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)
2026-05-19 17:53:11 +01:00
Temuri Doghonadze febfa1342e po: Translated using Weblate (Georgian)
Currently translated at 100.0% (270 of 270 strings)

Co-authored-by: Temuri Doghonadze <temuri.doghonadze@gmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/ka/
Translation: systemd/main
2026-05-19 16:01:24 +00:00
Marek Adamski 48bcf96d3b po: Translated using Weblate (Polish)
Currently translated at 100.0% (270 of 270 strings)

Co-authored-by: Marek Adamski <maradam@users.noreply.translate.fedoraproject.org>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/pl/
Translation: systemd/main
2026-05-19 16:01:23 +00:00
Yuri Chornoivan 7d8432485b po: Translated using Weblate (Ukrainian)
Currently translated at 100.0% (270 of 270 strings)

Co-authored-by: Yuri Chornoivan <yurchor@ukr.net>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/uk/
Translation: systemd/main
2026-05-19 16:01:23 +00:00
Luna Jernberg f424d7984e po: Translated using Weblate (Swedish)
Currently translated at 100.0% (270 of 270 strings)

Co-authored-by: Luna Jernberg <droidbittin@gmail.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/sv/
Translation: systemd/main
2026-05-19 16:01:22 +00:00
Américo Monteiro e2a49a7fae po: Translated using Weblate (Portuguese)
Currently translated at 100.0% (270 of 270 strings)

Co-authored-by: Américo Monteiro <a_monteiro@gmx.com>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/pt/
Translation: systemd/main
2026-05-19 16:01:21 +00:00
Oğuz Ersen d4fad9597c po: Translated using Weblate (Turkish)
Currently translated at 100.0% (270 of 270 strings)

Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/tr/
Translation: systemd/main
2026-05-19 16:01:21 +00:00
Daan De Meyer b13cc855e2 dependabot: Ignore mkosi
It doesn't update MinimumVersion= in mkosi.conf which breaks
tools/fetch-mkosi.py.
2026-05-19 16:36:39 +02:00
Luca Boccassi 881e4717c7 test: pin stress-ng --vm-method to a portable scalar method in TEST-55-OOMD
The stress-ng "vm" stressor's default --vm-method=all cycles through every
VM stress method, including newer ones that use AVX-512 instructions. On
CPUs without AVX-512 support (e.g. AMD Zen 1 to 3) those methods crash with
SIGILL. In testcase_oom_rulesets_lasting_sec all 10 stress-ng workers die
within ~2.34 seconds, so by the time the 6 second sleep elapses the unit
is already in failed/exit-code state and the assert_eq for
ActiveState=active trips.

Pin --vm-method=zero-one, a long-standing scalar method, on all four
stress-ng --vm invocations in this test (the two transient services in
testcase_oom_rulesets and testcase_oom_rulesets_lasting_sec, plus
TEST-55-OOMD-testbloat.service and TEST-55-OOMD-testmunch.service) so the
workers do not crash on AVX-512-less CPUs. testbloat, testmunch and
testcase_oom_rulesets have not been observed failing because they get
OOM-killed by systemd-oomd within ~1 to 2 seconds, before stress-ng cycles
into an AVX-512 method, but they share the same latent flake.

Journal excerpts from the failing run, TEST-55-OOMD-slowrule.service in
testcase_oom_rulesets_lasting_sec (journalctl -o short-monotonic):

[   58.018676] stress-ng[1015]: invoked with '/usr/bin/stress-ng --timeout 15s --vm 10 --vm-bytes 50M --vm-keep' by user 0 'root'
[   59.866072] stress-ng[1030]: stress-ng: debug: [1030] caught SIGILL, address 0x000055bd8d609140 (ILL_ILLOPN)
[   59.921050] stress-ng[1030]: stress-ng: debug: [1030] stress-ng: info: 0x000055bd8d609140:<62>71 fd 48 6f 2d 36 14 1c 00 c5 d1 ef ed 49 29
[   59.929310] stress-ng[1015]: stress-ng: error: [1015] vm: [1021] terminated with an error, exit status=2 (stressor failed)
[   60.364111] stress-ng[1015]: stress-ng: info:  [1015] failed: 10: vm (10)
[   60.364493] stress-ng[1015]: stress-ng: info:  [1015] unsuccessful run completed in 2.34 secs
[   60.371290] systemd[1]: TEST-55-OOMD-slowrule.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
[   60.371396] systemd[1]: TEST-55-OOMD-slowrule.service: Failed with result 'exit-code'.
[   64.017061] TEST-55-OOMD.sh[1010]: + assert_eq failed active
[   64.018167] TEST-55-OOMD.sh[1039]: FAIL: expected: 'active' actual: 'failed'

The faulting bytes marked by stress-ng with <62> (the byte at the
instruction pointer) decode unambiguously to an AVX-512 VMOVDQA64 using
the 512-bit zmm13 register, confirmed independently by two disassemblers:

  $ printf '\x62\x71\xfd\x48\x6f\x2d\x36\x14\x1c\x00' | ndisasm -b 64 -
  00000000  6271FD486F2D3614  vmovdqa64 zmm13,zword [rel 0x1c1440]
           -1C00

  $ echo '0x62, 0x71, 0xfd, 0x48, 0x6f, 0x2d, 0x36, 0x14, 0x1c, 0x00' | \
        llvm-mc -disassemble -triple=x86_64 -mattr=+avx512f
          .text
          vmovdqa64       1840182(%rip), %zmm13

The leading 0x62 is the EVEX prefix (exclusive to AVX-512 on this target),
zmm13 is a 512-bit register that only exists when AVX-512 is implemented,
and VMOVDQA64 requires the AVX512F (Foundation) CPUID feature (Intel SDM
Vol 2C). Executing this on a CPU without AVX-512 raises #UD, delivered by
the kernel as SIGILL/ILL_ILLOPN, matching the journal entry above. The
same journal shows the kernel reporting "kvm_amd: TSC scaling supported",
i.e. the guest is on AMD KVM, and AMD did not ship AVX-512 before Zen 4.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 15:07:25 +01:00
Lennart Poettering 3f0e95b7a8 vmspawn: port help() to help-util.h APIs 2026-05-19 15:00:09 +01:00
Luca Boccassi fed82f2a68 Update NEWS 2026-05-19 14:56:24 +01:00
Luca Boccassi ea2448bea0 homed/fscrypt: add new xattr format hardening key sealing (#41816)
The current key sealing format has some less-than-ideal weaknesses:

- PBKDF2 with only 65k iterations, where recommendations are ~200k
- AES with null IV, relying on salt for uniqueness
- lack of AES MAC/AEAD

However improbable, it is at least theorically possible that with
a lot of resources an offline bruteforce could be attempted.

Add a v2 sealing format, keeping unsealing compatibility with
the current format:

 `v2:<iterations>:<salt>:<IV>:<ciphertext>:<aes tag>`

and use 600k iterations for the PBKDF2 sha512
2026-05-19 14:56:18 +01:00
Lennart Poettering 781d86864c update TODO 2026-05-19 14:41:45 +02:00
Lennart Poettering 86e74db277 some NEWS fixed by Claude 2026-05-19 14:35:29 +02:00
Luca Boccassi 4a82fc67c6 homed/fscrypt: add new xattr format hardening key sealing
The current key sealing format has some less-than-ideal weaknesses:

- PBKDF2 with only 65k iterations, where recommendations are ~200k
- AES with null IV, relying on salt for uniqueness
- lack of AES MAC/AEAD

However improbable, it is at least theorically possible that with
a lot of resources an offline bruteforce could be attempted.

Add a v2 sealing format, keeping unsealing compatibility with
the current format:

 v2:<iterations>:<salt>:<IV>:<ciphertext>:<aes tag>

and use 600k iterations for the PBKDF2 sha512
2026-05-19 13:35:19 +01:00
Vincent Mihalkovic b5d5362069 fstab-generator: fix spurious quota warning for xfs
Filesystems like xfs, btrfs, gfs2 and ocfs2 handle quotas internally
and do not need external quotacheck/quotaon services. When usrquota or
grpquota mount options are used in fstab for these filesystems,
generator_hook_up_quotacheck() falls through to the !fstype_needs_quota()
branch and emits a misleading warning that quotas are "not supported"
when they actually work fine — the kernel handles them internally.

Add fstype_has_internal_quota() to return early with a debug message,
and adopt a tri-state return convention so the caller skips quotaon
when quotacheck was not needed.

The buggy code path was introduced in #24824 and #24880.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-19 13:12:43 +01:00
Luca Boccassi a332f3b6ca test: add test coverage for homed+fscrypt
Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 12:36:44 +01:00
Lennart Poettering 6695167aea update TODO 2026-05-19 13:20:39 +02:00
Emanuele Rocca ed143d8623 coredump: add COREDUMP_CODE field for signal reason
Introduce COREDUMP_CODE as a new captured field alongside the existing
COREDUMP_SIGNAL. While COREDUMP_SIGNAL identifies the signal number that
terminated the process, COREDUMP_CODE provides the reason the signal was sent.

For example, a process terminated by SIGSEGV due to invalid permissions would
produce COREDUMP_SIGNAL=11 and COREDUMP_CODE=2 (SEGV_ACCERR).

The kernel exposes coredump_code via pidfd starting with v7.1:
https://git.kernel.org/torvalds/c/701f7f4fbabbf4989ba6fbf033b160dd943221d5

System administrators can find both the signal and code in coredumpctl info:

$ coredumpctl info | grep Signal:
        Signal: 11 (SEGV) si_code: SEGV_MAPERR

Signed-off-by: Emanuele Rocca <emanuele.rocca@arm.com>
2026-05-19 08:28:53 +00:00
Emanuele Rocca c8c1bcf194 signal-util: add signal_code_to_string
Add signal_code_to_string() in signal-util.c and cover the si_code values
defined in libc's siginfo-consts.h. Fall back to the numeric value when no
symbolic name is known.

Co-developed-by: Codex (GPT-5) <noreply@openai.com>
Signed-off-by: Emanuele Rocca <emanuele.rocca@arm.com>
2026-05-19 08:14:36 +00:00
Emanuele Rocca 577f2f975d include: add coredump_code to struct pidfd_info
Linux v7.1 adds coredump_code to struct pidfd_info and defines a few new
constants. Reflect the changes in include/override/sys/pidfd.h too.

Stop including the libc version of sys/pidfd.h to be able to override the
definition of pidfd_info.

Signed-off-by: Emanuele Rocca <emanuele.rocca@arm.com>
2026-05-19 08:14:18 +00:00
Daan De Meyer bdbcff6530 Various dlopen/linking cleanups from #42100 (#42166)
- **bpf-util: rename from bpf-dlopen, unify version-specific symbol
handling**
- **cryptsetup: dlopen libcryptsetup in tokens**
- **tree-wide: dlopen libpam in pam plugins**
- **test-bus-marshal: dlopen() glib and libdbus instead of linking
directly**
- **lock-util: Simplify timeout for lock_generic_with_timeout()**
- **color-util: simplify hsv_to_rgb, fix rgb_to_hsv negative-hue wrap**
- **tree-wide: Use our own macros instead of fabs()/fmax()/fmin()**
- **locale-util: dlopen() libintl instead of linking against it**
- **home: Use log2u64() over log2()**
- **meson: drop libdl, threads, and librt dependencies**
- **libc: Use dlsym() from a constructor instead of weak symbols**
- **libc: Make sure C23 versions of strtol(), sscanf() are not used**
2026-05-19 08:54:27 +02:00
Dmitry Konishchev 0614602dfa Fix an invalid section in example for NFTSet
`NFTSet` is supposed to be in `Service` instead of `Unit` section. The current example leads to `Unknown key 'NFTSet' in section [Unit], ignoring` in systemd logs.
2026-05-19 15:48:05 +09:00
Lennart Poettering 7383a01ffe dissect: guard against ssize_t overflow in LUKS2 header parser (#42162)
The `json_len` variable in `partition_is_luks2_integrity()` is
`ssize_t`, but the subtraction `be64toh(header.hdr_len) -
LUKS2_FIXED_HDR_SIZE` can yield a value exceeding `SSIZE_MAX` when
`hdr_len` is a large crafted value. This causes signed integer overflow
and a subsequent oversized `malloc()` that fails with `-ENOMEM`,
producing a misleading out-of-memory error instead of a clear
invalid-header rejection.

Two call sites pass `size = UINT64_MAX`, which neutralizes the existing
`hdr_len > size` guard.

Add an explicit check against `SSIZE_MAX` before the cast to `ssize_t`.
2026-05-19 08:30:07 +02:00
TristanInSec aa76d81122 resolved: add missing polkit checks on FlushCaches and ResetServerFeatures D-Bus methods
The FlushCaches and ResetServerFeatures D-Bus methods perform
destructive operations (flushing all DNS caches and resetting server
feature negotiation including DNS-over-TLS state) without any
authorization check. The corresponding Varlink methods already enforce
polkit via verify_polkit(), but the D-Bus handlers were not updated.

Add bus_verify_polkit_async() calls to both methods, matching the
pattern used by ResetStatistics. Add the corresponding policy actions
to the polkit policy file.
2026-05-19 08:29:34 +02:00
Lennart Poettering 9a8e2f17ef update NEWS 2026-05-18 23:43:27 +02:00
Lennart Poettering 606698ec74 update NEWS 2026-05-18 23:17:50 +02:00
Daan De Meyer 97f81508c5 libc: Make sure C23 versions of strtol(), sscanf() are not used
When _GNU_SOURCE is defined, glibc will always use c23 versions
of strtol(), sscanf() and friends if available (introduced after
glibc 2.34). Which means that any binaries built with headers
from newer glibc won't load on glibc < 2.38. To work around this,
redefine the appropriate constants to zero make sure the c99 
versions are used instead.
2026-05-18 21:17:38 +00:00
Daan De Meyer b77c7b7cfc libc: Use dlsym() from a constructor instead of weak symbols
Weak symbols still introduce a version requirement on a newer libc.
Resolve each libc symbol via dlsym(RTLD_DEFAULT) from a per-shim
constructor and cache the result in a file-scope static instead. This
avoids the version requirement, keeps the call path free of atomics
(constructors run single-threaded before main() and before any signal
handler can fire), and keeps dlsym() out of contexts where it is not
async-signal-safe.
2026-05-18 21:17:38 +00:00
Daan De Meyer a14adac423 meson: drop libdl, threads, and librt dependencies
Our baseline glibc is 2.34, which merged libdl, libpthread (the
dependency('threads') target), and librt into libc. Empty .so/.a stubs
remain for backward compatibility with old binaries, but new builds
resolve dl_*, pthread_*, mq_*, timer_*, etc. directly from libc.
On musl the same libraries are likewise empty stubs.

Drop the libdl, threads, and librt entries from every meson.build, and
remove the now-stale 'Libs.private: -lrt -pthread' from libudev.pc.in
since both flags resolve to empty link-time stubs on glibc 2.34+ and
musl.

Verified with readelf -d that libsystemd.so, libudev.so, and systemd no
longer carry DT_NEEDED entries for libdl/libpthread/librt.
2026-05-18 21:17:38 +00:00
Daan De Meyer 5a1644de34 home: Use log2u64() over log2()
And drop the libm dependency.
2026-05-18 21:17:38 +00:00
Daan De Meyer e6e65dc261 locale-util: dlopen() libintl instead of linking against it
dgettext() lives in libc on glibc and in libintl.so.8 on musl with
gettext. Resolve it via dlsym() so neither configuration produces a
hard link-time dependency on libintl: try libintl.so.8 first and fall
back to RTLD_DEFAULT (which finds dgettext in libc on glibc).

The _() macro now expands to a runtime check that returns the
untranslated string if dlopen_libintl() has not run successfully, so
callers don't have to gate every translatable message on a runtime
check. pam_systemd_home — currently the only consumer of _() — calls
dlopen_libintl() best-effort from each PAM entry point.

The meson find_library('intl') dance is replaced with a has_header()
check; the only thing we need at build time is the prototype.
2026-05-18 21:17:38 +00:00
Daan De Meyer b2bfe5b474 tree-wide: Use our own macros instead of fabs()/fmax()/fmin()
To make this work, ABS() is made generic so it also works on
floats and doubles.

While at it, fold the __ABS_INTEGER indirection and the
assert_cc(sizeof(long long) == sizeof(intmax_t)) away. The previous
form switched between __builtin_llabs (clang) and __builtin_imaxabs
(gcc), with the assert keeping the two paths behaviorally identical
on every platform we build for. imaxabs was originally chosen because
intmax_t is conceptually the widest signed integer type the platform
exposes, but the _Generic ABS already casts to (long long) before the
call, so the extra width imaxabs could in theory carry was being
narrowed away immediately anyway. With both paths collapsed to
__builtin_llabs((long long) (a)), the size relationship between
long long and intmax_t is no longer relevant.

Also add explicit unsigned long long / unsigned long / unsigned int
cases that pass the argument through unchanged. The previous default
branch cast unsigned values to (long long); for values above LLONG_MAX
this reinterprets them as negative, and __builtin_llabs(LLONG_MIN) is
UB. Unsigned values are already non-negative, so passing them through
is both correct and avoids the narrowing. Smaller unsigned types
(unsigned char, unsigned short) still go through the default branch
but promote to int first and fit in long long losslessly.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 21:17:38 +00:00
Daan De Meyer 7d2925fcde color-util: simplify hsv_to_rgb, fix rgb_to_hsv negative-hue wrap
In hsv_to_rgb, restructure the conversion around the sector index
k = (int)(h/60) and fractional offset f = h/60 - k. The auxiliary
x value becomes c * (k & 1 ? 1.0 - f : f) and the six branches turn
into a switch on k. This drops the two xfmod() calls that were doing
the modulo work, in exchange for a single assert(h >= 0 && h < 360) —
all in-tree callers satisfy this and never relied on the wrap.

In rgb_to_hsv, the two xfmod() calls were no-ops (their arguments
were always within the divisor's magnitude). The trailing
xfmod(*ret_h, 360) appeared to be wrapping negative hues from the
r-max branch back into [0, 360), but fmod is sign-preserving so it
never did. Drop the no-ops and add an explicit +360 wrap so magenta
(1, 0, 1) now yields h ≈ 300 instead of -60.

Extend the tests to cover all six primary/secondary colors at sector
boundaries, all six sector midpoints (to catch any future inversion
of the ramp direction), the h-near-360 edge of the last sector, and
the rgb_to_hsv negative-wrap path via magenta. Switch the new and
existing integer-channel checks to ASSERT_EQ from tests.h; the
double-typed h/s/v range checks stay on ASSERT_TRUE since the
ASSERT_* comparison macros only support integer types.

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 21:17:38 +00:00
Daan De Meyer bcb7cf4a61 lock-util: Simplify timeout for lock_generic_with_timeout()
We can just put a timeout on the parent process completing 
rather than doing it inside the subprocess.
2026-05-18 21:17:38 +00:00
Daan De Meyer 0af0161f55 test-bus-marshal: dlopen() glib and libdbus instead of linking directly
The test only uses 9 symbols (5 from glib, 4 from libdbus) for its
interop checks; dlopen them at runtime so the binary no longer carries a
hard link-time dependency on either library. Headers are still pulled in
through the *_cflags partial dependencies for the type declarations.

While we're at it, drop the compat glue for glib 2.36 which is long obsolete
at this point.
2026-05-18 21:17:38 +00:00
Daan De Meyer 62053ee289 tree-wide: dlopen libpam in pam plugins
Same reasoning as for cryptsetup tokens. It means we can include
the pam plugins in the main systemd package without the package 
manager introducing a dependency on libpam. It also makes things
more consistent and makes writing the upcoming linking test script
a lot simpler.

At the same time, we get rid of the libpam_misc dependency as the
one symbol we were using from it is trivial to reimplement ourselves.
2026-05-18 21:17:38 +00:00
Daan De Meyer 94d745c42c cryptsetup: dlopen libcryptsetup in tokens
This avoids having to subpackage the tokens separately. If they link directly
against libcryptsetup, package manager will automatically add a dependency on
libcryptsetup to the package containing the tokens. With this change, the tokens
can ship in the main systemd package without necessarily pulling in libcryptsetup.

It also makes things more consistent. Once we also do the same for pam, any direct
linking will be limited to just libc, which for example simplifies writing tests for
ensuring we don't link unnecessarily as we don't have to add exceptions for the
cryptsetup tokens.

This actually drops the dependency on cryptsetup-libs for the fedora/centos/opensuse
systemd-udev package so install it explicitly in the initrd now to keep the tests
working.
2026-05-18 21:17:38 +00:00
Daan De Meyer 7d822ca8af bpf-util: rename from bpf-dlopen, unify version-specific symbol handling
Renames src/shared/bpf-dlopen.{c,h} to src/shared/bpf-util.{c,h} and
folds the former src/shared/bpf-compat.h (struct forward decl and
compat_bpf_map_create() helper) into the new header.

Aligns dlopen_bpf() with the standard wrapper pattern: drops the
manual dlopen_safe()/dlsym_many_or_warn()/TAKE_PTR(dl) plumbing and
the bespoke 'cached' int in favor of dlopen_many_sym_or_warn() inside
a FOREACH_STRING() soname-fallback loop.

Unifies declaration of the version-specific symbols (bpf_create_map,
bpf_map_create, bpf_object__next_map, bpf_token_create) into a single
DISABLE_WARNING_REDUNDANT_DECLS block in the header, and alphabetically
merges the DLSYM_PROTOTYPE list. DLSYM_OPTIONAL is used to load each
one — call sites already handle NULL (compat_bpf_map_create() and the
sym_bpf_object__next_map guard in userns-restrict.c). bpf_token_create
additionally defaults to a missing_bpf_token_create() stub returning
-ENOSYS, so callers can branch on the errno instead of NULL-checking
the pointer.

Updates test-bpf-token to match: drops the compile-time
LIBBPF_MAJOR_VERSION ≥ 1.5 gate and the direct <bpf/bpf.h> include in
favor of dlopen_bpf() + sym_bpf_token_create(), and treats -ENOSYS as
the test-skip path (covering both 'libbpf too old' and 'kernel lacks
BPF_TOKEN_CREATE support').
2026-05-18 21:17:38 +00:00
Luca Boccassi 82b47c79bd import: Handle small files (#42150)
When systemd-pull encountered a file shorter than the compression magic
    headers it looks for, then it would complete the download in the
    analysis state and fail.
    When we are still in the analysis state and the download is done, we
know there is no compression and we should leave the analysis state and
    continue writing out to disk as usual.
2026-05-18 21:47:41 +01:00
Matteo Croce 15783e4657 oomd: ruleset parsing
Add to oomd the capability to define rulesets in /etc/systemd/oomd/rules.d/
and then reference them with a new config option OOMRule=
2026-05-18 21:42:56 +02:00
TristanInSec a190e64dfb dissect: use practical 16 MiB limit instead of SSIZE_MAX
As suggested by @yuwata, SSIZE_MAX is still too large and would cause
malloc() to fail anyway. Use a 16 MiB limit which is generous compared
to the typical 4 MiB maximum in cryptsetup (LUKS2_HDR_OFFSET_MAX).
2026-05-18 14:39:44 -04:00
TristanInSec 08c281304c dissect: guard against ssize_t overflow in LUKS2 header parser
The json_len variable is ssize_t, but the subtraction
be64toh(header.hdr_len) - LUKS2_FIXED_HDR_SIZE can yield a value
exceeding SSIZE_MAX when hdr_len is a large crafted value. This causes
signed integer overflow and a subsequent oversized malloc() that fails
with -ENOMEM, producing a misleading out-of-memory error.

Add an explicit check against SSIZE_MAX before the cast to ssize_t.
2026-05-18 13:30:02 -04:00
Ivan Kruglov 6080d1cc42 errno-util: include -ENOENT in ERRNO_IS_XATTR_ABSENT()
The getxattr(2) man page only enumerates xattr-specific errors (ENODATA,
ENOTSUP, ERANGE, E2BIG, ...) in its own ERRORS section, but at the
bottom of that section notes that "the errors documented in stat(2) can
also be returned." stat(2) returns -ENOENT when a component of the path
does not exist, so any xattr lookup against a path can fail with -ENOENT
exactly the same way as -ENODATA — both mean "there is nothing here for
me to read." The previous definition of ERRNO_IS_NEG_XATTR_ABSENT()
reflected only the directly-enumerated errors and missed -ENOENT, so
callers that should semantically swallow "the xattr is absent" instead
bubbled -ENOENT up as a hard error.

The most visible consequence on real fleets has been systemd-journald
spamming dmesg with one line per dispatched log message whenever a
unit's cgroup directory cannot be found at the time
client_context_read_log_filter_patterns() is called — typically inside
containers whose journald observes clients whose unit cgroup is no
longer present in its view (cgroup-namespace boundary, unit teardown
race, transient sub-scope already collapsed back to its unit cgroup,
etc.). The same bug pattern lurks at every other cgroup-xattr callsite:
systemd-oomd reading user.oomd_avoid / user.oomd_omit / user.oomd_ooms
on cgroups it is concurrently killing; killall reading
user.survive_final_kill_signal during shutdown; cg_is_delegated() /
cg_has_coredump_receive() / cgroup_get_managed_oom_kill_last(); etc. For
these, "path is gone" is by construction the same answer as "xattr is
not set" — there is no way for the user to have attached an xattr to a
path that does not exist.

A quick survey of non-cgroup callers (src/portable/portable.c,
src/home/{homework-luks,user-record-util}.c,
src/random-seed/random-seed-tool.c, src/basic/os-util.c) confirms they
all operate on fds or on paths whose absence is already the desired
silent-skip outcome, so widening the macro to also fold in -ENOENT does
not change observable behavior at any other site.

Extend test-xattr-util's getxattr_at_malloc test with an explicit
non-existent-path lookup that asserts ERRNO_IS_NEG_XATTR_ABSENT() now
matches, alongside the pre-existing non-existent-xattr (-ENODATA) check.
2026-05-19 01:45:54 +09:00
Luca Boccassi 6fa5ebc506 dhcp-client: reject messages larger than the maximum UDP payload
dhcp_message_verify_header() only enforced a lower bound on the input
length, so dhcp_message_parse() happily accepted arbitrarily large
buffers. Such inputs could never have been received via UDP and would
later fail in dhcp_message_build() with -E2BIG once the parsed options'
combined size exceeds UDP_PAYLOAD_MAX_SIZE, which the fuzzer surfaced as
an assertion failure.

Reject inputs above UDP_PAYLOAD_MAX_SIZE up front, so the parse stage
mirrors what the wire format can actually carry.

Follow-up for 8c18bb6547

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

Co-developed-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 01:43:25 +09:00