Author SHA1 Message Date
SymbX 2731560250 workaround for waitpid 2026-10-29 22:33:28 +02:00
SymbX afa212d153 workaround to support pidfd_open (backported) while waitpid is missing 2026-10-29 22:33:28 +02:00
SymbX 93b7d20dcc revert changes to apply with system where kernel is 4.19 2026-10-29 22:33:27 +02:00
Luca Boccassi 73612ea502 meson: bump version to 262.1 2026-10-16 17:24:52 +01:00
Luca Boccassi aa0c421647 hwdb: update to main@{2026-10-15}
git restore -s origin/main hwdb.d/ test/hwdb.d
2026-10-16 17:24:52 +01:00
Yu Watanabe 29b1d05549 mkosi: update nura commit reference to 7a6b81a4f1a7a510d088a5874bebcf2b200b69b3
* 7a6b81a4f1 Revert "systemd/systemd: build with SELinux support"
* 1e70e1b89a systemd/systemd: add patch to fix nsresourced failure

Alpine updated linux-pam 1.7.1-r3 to 1.7.1-r4, which disables SELinux
support again [1]. Hence, systemd also needs to be built without
SELinux support [2]. Otherwise, all operations that require PAM fail.

[1] https://gitlab.alpinelinux.org/alpine/aports/-/commit/f3734bec196117b7972c32545594f3ab3a53a111
[2] https://gitlab.postmarketos.org/postmarketOS/pmaports/-/commit/7a6b81a4f1a7a510d088a5874bebcf2b200b69b3

(cherry picked from commit 6645aa57a2e20678007424ca9125efa99df2925d)
2026-10-16 17:24:52 +01:00
Paul Meyer 659d194912 ci: skip push-triggered jobs on forks
Syncing a fork's main branch triggers the push workflows if actions are
enabled, which then run the full CI matrix and use up the fork owner's
Actions minutes for no benefit. Only skip push events so that PRs within
a fork still run CI, which is useful for testing actions.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
(cherry picked from commit 4c63532c28094aeba6dccc5afb9690e02fd98d66)
2026-10-16 17:24:52 +01:00
dependabot[bot] f9f3c11f40 build(deps): bump the actions group with 4 updates
Bumps the actions group with 4 updates: [github/codeql-action/upload-sarif](https://github.com/github/codeql-action), [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials), [redhat-plumbers-in-action/differential-shellcheck](https://github.com/redhat-plumbers-in-action/differential-shellcheck) and [softprops/action-gh-release](https://github.com/softprops/action-gh-release).

Updates `github/codeql-action/upload-sarif` from 4.37.8 to 4.38.2
- [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/db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2)

Updates `aws-actions/configure-aws-credentials` from 6.2.3 to 6.3.0
- [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/e6de054238d6b7531b4efff3b6587d9aade6a06c...e1253824e5c10ff9df46874f81ed3ec929e19cfd)

Updates `redhat-plumbers-in-action/differential-shellcheck` from 5.5.6 to 5.5.7
- [Release notes](https://github.com/redhat-plumbers-in-action/differential-shellcheck/releases)
- [Changelog](https://github.com/redhat-plumbers-in-action/differential-shellcheck/blob/main/docs/CHANGELOG.md)
- [Commits](https://github.com/redhat-plumbers-in-action/differential-shellcheck/compare/d965e66ec0b3b2f821f75c8eff9b12442d9a7d1e...f51c7c0d32777d00de777131d25918617a246415)

Updates `softprops/action-gh-release` from 3.0.2 to 3.0.3
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/3d0d9888cb7fd7b750713d6e236d1fcb99157228...efb35369e0ad2afab669f228072c1b0d510eae64)

---
updated-dependencies:
- dependency-name: github/codeql-action/upload-sarif
  dependency-version: 4.38.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: aws-actions/configure-aws-credentials
  dependency-version: 6.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: redhat-plumbers-in-action/differential-shellcheck
  dependency-version: 5.5.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: softprops/action-gh-release
  dependency-version: 3.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 8de82afa1055428b1a0adc0f78be789a62fb7a9f)
2026-10-16 17:24:52 +01:00
dependabot[bot] 69dde70fba build(deps): bump ninja from 1.13.0 to 1.13.2 in /.github/workflows
Bumps [ninja](https://github.com/ninja-build/ninja) from 1.13.0 to 1.13.2.
- [Release notes](https://github.com/ninja-build/ninja/releases)
- [Commits](https://github.com/ninja-build/ninja/compare/v1.13.0...v1.13.2)

---
updated-dependencies:
- dependency-name: ninja
  dependency-version: 1.13.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 7c6462fe374fd1426835896ee7a9d4e1fa417e11)
2026-10-16 17:24:52 +01:00
LevitatingBusinessMan (Rein Fernhout) 67e054aa5a mkosi,test: rename postmarketos to nura
Recently, postmarketOS is renamed to Nura:
See https://postmarketos.org/blog/2026/09/27/nura-rename/

mkosi already renamed postmarketOS to Nura:
https://github.com/systemd/mkosi/commit/580c4d94d75ef18f2a0983626cfd80bea9c44ece

Co-authored-by: Yu Watanabe <watanabe.yu+github@gmail.com>
(cherry picked from commit e9090fe18086edf48ef9f2ab420366b3c5f1d027)
2026-10-16 17:24:52 +01:00
LevitatingBusinessMan (Rein Fernhout) 42ef35b4bb mkosi: update mkosi ref to 71d7b67e01dc47ab5c51f24866c3e2195b9701d2
* 117d382486 nura: use modern url for Alpine binary repos
* 7872fd58f7 nura: drop x86
* 3533864541 gitignore: add mkosi.pkgcache
* 580c4d94d7 Rename postmarketOS --> Nura
* ba96aba91e Bump version to 28~devel

(cherry picked from commit b2b8be184edf39022c59eaa5b0fd365eb19afc44)
2026-10-16 17:24:52 +01:00
Yu Watanabe dde7f097eb github: install APK for testing postmarketOS
Since https://github.com/systemd/mkosi/commit/b9d4c0623975d75788627c114147be394939c7cb,
APK is not installed by default. Install it when using postmarketOS.

(cherry picked from commit 70e73a0b3fddf6fba860f7d255f7b886b02413ac)
2026-10-16 17:24:52 +01:00
Yu Watanabe b9213b167d mkosi: update mkosi ref to ecf7f5702bb2052b7a69cab3fe7d37bc3b9ad77b
* ecf7f5702b Release 27.1
* ca08e2ccef docs: add notes on nsresourced in execution flow
* 146b5dd4de docs: add a few notes on package manager specific behaviour
* 344e42ee20 Update NEWS
* dde1bf020f debian: fix debian-security/debug url when using a mirror
* 699aa3b565 mkosi: upgrade debug message about fallback path to info
* cb6da3f3ce mkosi: move fallback environment variable check to bypass nsresourced fully
* 88c716a6b9 config: add delegate_ranges
* f4de9a102a mkosi: use the foreign UID range only when requested when running as root
* d091fed134 mkosi: only delegate UID ranges if we're not already root
* 165bc99675 sandbox: rename delegate to delegate_ranges
* bba53c50d0 sandbox: use equality check instead of boolean not for delegate
* a033d03f59 summary: add foreign uid range
* f13e96eb95 user: drop unused variable SUBRANGE
* 847d113863 mkosi-obs: Only configure MakeScriptsExecutable in the main image
* 568b1bce56 dnf: Only read repositories and variables from the sandbox tree
* 938d6a1c21 obs: use policy signing data when available
* 19d045e5e9 Rename sysupdate configuration files to .transfer
* 9539f1771a action: bump fallback apk version to 3.0.8
* 8de4d25596 sandbox: add force_fallback to acquire_privileges and wire it up via env
* af97d6ffef opensuse: tolerate missing RPM keyring
* 0f2b7e0656 initrd: don't fail when encountering directories among ucode files
* 5240191893 Allow using SignInitrdPCRs with SplitArtifacts=pcrs
* ce90009686 Bump ukify required version from 261.999 to 262~ for SignInitrdPCRs
* 58bbd63aca news: fix v27 `DiskType=` setting typo
* 1da3299aec tests: skip test_fork_and_wait if on rc 1
* 5658e7abc9 Bump version to 28~devel
* 4736cd8361 Release 27
* 97f305bf0a action: make shell style consistent
* dd7140cbae action: only use apk version from API if non-empty
* 2cfe0cefb8 news: update NEWS
* 7bca598fa4 action: support container-based self-hosted runners
* 08c86a25e1 action: bump fallback APK version
* cc0fcef38f action: reduce timeouts and number of API calls
* 211993d5d2 action: download latest version of apk
| * f33cc45db3 Add ToolsTreeSnapshot= for pinning the default tools tree
| * ddfc5a2cb5 tests: join options and their values with f-strings
| * a497ff0251 doc: add missing matchers
* | 589226cfd4 apk: disable grub's update-grub trigger during package installation
 /
| * 595451bb4b debian: add new split-out systemd packages
| * 7ce1851901 Revert "mkosi-tools: Install systemd-tpm on Debian"
| * 50a1137be5 ci: pin resolved release for integration tests
| * e30b0a0ba4 tests: drop obsolete @ prefix
| * e7f4d57fac news: update NEWS
|/
* bf2addb2ec build(deps): bump aws-actions/configure-aws-credentials
* a58ded6a2a build(deps): bump actions/checkout from 6.0.2 to 7.0.1
* 9b7d87a170 add support for prebuilt UKIs
* 75fdb9be15 mkosi-tools: Install systemd-tpm on Debian
* d5ff0d0d98 Fall back to unprivileged user namespace on polkit denial
* 0e4d5546ac Bump 261~devel version checks to 261
* 180d4a5329 Use systemd nightly OBS version in signing PCR policies auto detection
* f7401bdc8d Add support for signing PCR policies for the initrd
* 33d17b2b92 sandbox: Don't create shared propagation peer group
* a078088f8e sandbox: Declare MS_PRIVATE as well
* e1e9eafc87 kmod: eliminate duplication in calls to modinfo
* df68b27e8e tools: add mount to Debian tools tree
* 205dcedd45 util: don't drop single-character variable names in read_env_file
* 35a9d38ea0 distribution: report the actual architecture in unsupported-arch errors
* d4f44d212c sandbox: handle case where dev node for tty doesn't exist better
* acf08c5eca build(deps): bump actions/upload-artifact from 7.0.0 to 7.0.1
* b3ec53743a tests: Pass --output-directory to vm() and boot()
* 9bc430a7fa config: Isolate build history per output directory
* fd3d9bfe57 tests: Add regression test for build history lookup via configured output dir
| * 55ab00bb13 Fix tar exclude patterns for apivfs paths
|/
* 699da862f8 sandbox: Split a chroot() context manager out of chase()
* 70ce10d132 sandbox: Default FSOperation.execute oldroot/newroot to /
* 610b38538f Forbid AI attribution in commit messages
* b7425bbe42 ci: Sync claude-review workflow with systemd
* b9d4c06239 action: Make apk installation configurable and reliable again

(cherry picked from commit 280dd84243c387af7510b727d123390fa9c61dc7)
2026-10-16 17:24:52 +01:00
Yu Watanabe af8c7cdfbe mkosi: update postmarketos commit reference to f908244ec2a0f85a84f44927183711160a798705
* f908244ec2 systemd: move tmpfiles.d/systemd-network.conf to networkd subpackage

Fixes the following warning on mkosi build:
```
‣ [default-initrd]  Copying in extra file trees…
‣ [default-initrd]  Generating system users
‣ [default-initrd]  Generating volatile files
/buildroot/usr/lib/tmpfiles.d/systemd-network.conf:13: Failed to resolve user 'systemd-network': Unknown user
‣ [default-initrd]  Applying presets…
```

(cherry picked from commit decaca402046ef7d7749d39ba8598deff90fa6b8)
2026-10-16 17:24:52 +01:00
Yu Watanabe 9405a6da2f mkosi/postmarketos: drop unnecessary musl-utils
It was installed for ldconfig.service, but it is disabled now:
https://gitlab.postmarketos.org/postmarketOS/pmaports/-/commit/131f1be52ebec9cc6697b42c226581e1322558f7

(cherry picked from commit bc5de99fd0)
2026-10-16 17:24:52 +01:00
Yu Watanabe a1a79e94ab mkosi: update postmarketos commit reference to 07ea0bed8fbbafe06b2bf68b6bfabcf86c2e4449
* 07ea0bed8f systemd: drop unnecessary dependencies
* 45eb7f88dc systemd/systemd: upgrade to 262
* cb9121da2c systemd/systemd: upgrade to 262_rc3
* 6c223d3566 systemd: drop pre-install script, re-exec on upgrade
* 10591797ee systemd: upgrade to 262-rc2
* 7d5b4e3816 systemd/systemd: build with SELinux support
* bb647faf54 systemd: upgrade to 262-rc1
* 369c5ac3b6 extra-repos/systemd: backport timesyncd DNSSEC NTP fix
* 2bf2f3329e treewide: remove pmb:strict from options
* 9c68abf912 systemd/systemd: upgrade to 261.2
* 3004382975 systemd: remove eudev provide
* 131f1be52e systemd/systemd: disable ldconfig
* 6e90d14c4d systemd/systemd-stage0: disable unnecessary options
* a372a2f2c5 systemd/systemd: backport patch adding inhibit support to pam_systemd
* 994ed89373 systemd/systemd: add Ollie as co-maintainer
* 14897810c9 systemd: disable compat-sysv-interfaces
* 5e5a451de1 systemd: remove unnecessary provider_priority's
* 61ee5c6fe8 treewide: remove contributor comments
* f36462e85b systemd/systemd: upgrade to 261.1
* 5ff3f5ed44 systemd/systemd: adds libbz2 dependency

(cherry picked from commit 35034dbdcd)
2026-10-16 17:24:52 +01:00
Yu Watanabe 8221879cdd mkosi: drop unnecessary packages
This partially reverts 77b3ddf2aa.

Testing with musl is now done by postmarketOS. Hence, these packages
are not necessary anymore.

(cherry picked from commit fd1f164b1b)
2026-10-16 17:24:52 +01:00
Christian Hesse 734cb86748 mkosi: update arch commit reference to 4749b653ee7b9210bcd46fe43065508aa58b779a
(cherry picked from commit 327061908a)
2026-10-16 17:24:52 +01:00
Lennart Poettering 385eaf8f94 import: drain trailing archive null padding in tar-x child
libarchive stops reading as soon as it hits the end-of-archive marker,
but tar archives are usually padded with zeroes to a full record size
after that (GNU tar uses 10K records by default). Since the tar-x child
then exits right away, the importer's final write of that padding can
race against the child exiting and fail with EPIPE:

    Imported 88%.
    Failed to decode and write: Broken pipe

The child exits successfully in this case, hence no tar error is logged
at all. Seen in TEST-13-NSPAWN on "machinectl import-tar" of a
"tar -czf" generated tarball.

Fix this by reading the input pipe to EOF after tar_x() returns
successfully, verifying that whatever follows the end-of-archive marker
is all zeroes, and refusing the archive otherwise. This affects
importctl import-tar as well as pull-tar and pull-oci.

This addresses Ci failures such as:

https://github.com/systemd/systemd/actions/runs/38738219126/job/116432869392?pr=44163
(cherry picked from commit 9c852031ec8178256196380dc9866553ce37842f)
2026-10-16 17:24:52 +01:00
Lennart Poettering 4cf713b8ab docs: two follow-ups for NV Index registry commit
As per review comments on https://github.com/systemd/systemd/pull/33394

Follow-up for: 6e12c598d34eb9345d8c000f1abe790f4d79c5c5

(cherry picked from commit cc76554de0736ec5623635493cb238620c589da8)
2026-10-16 17:24:52 +01:00
Lennart Poettering 38a75c5433 doc: add document stating how we assign NV indexes
The Trusted Computing Group has assigned the systemd project an NV index
range, let's document properly which one that is, and how we use it.

Thank you so much, TCG!

(cherry picked from commit 6e12c598d34eb9345d8c000f1abe790f4d79c5c5)
2026-10-16 17:24:52 +01:00
Ard Biesheuvel c0d07a288d efi: Avoid register X18 on AArch64 builds
The UEFI spec does not permit the use of register X18 on the AArch64
architecture, on the basis that it is a platform register that may have
a special use in the platform.

This is not usually the case at boot time in UEFI implementations known
today, but it should be avoided nonetheless.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
(cherry picked from commit 78a159bb74cca9e8870f68b2353e88e42b3d0f39)
2026-10-16 17:24:52 +01:00
Daan De Meyer c06a76f5c4 ci: fail the linter while the README notice is present
The labeler converts a PR to a draft while README.md has the review
notice. Nothing else stops a merge. If the labeler fails, or somebody
merges before it runs, the PR goes in with the notice.

Let's add a linter job that fails when README.md has the notice. We keep
it out of the main lint job. That way it doesn't wait for the tools tree
build, and it can be made a required status check by itself.

(cherry picked from commit f1ea185bcf5f3f286c92b015294190b23f7215f5)
2026-10-16 17:24:52 +01:00
Jörg Behrmann dab14842b6 ukify: merge example config file section
Since the example config file is generated in order of ConfigItems this added a
second [UKI] section

    [UKI]
    …
    SignKernel = SIGN_KERNEL

    [PCRSignature:NAME]
    PCRPrivateKey = PCR_PRIVATE_KEYS
    PCRPublicKey = PATH
    PCRCertificate = PATH
    Phases = PHASE-PATH…
    PolicyRef = STRING

    [UKI]
    SignInitrdPCRs = SIGN_INITRD_PCRS

which becomes

    [UKI]
    …
    SignKernel = SIGN_KERNEL
    SignInitrdPCRs = SIGN_INITRD_PCRS

    [PCRSignature:NAME]
    PCRPrivateKey = PCR_PRIVATE_KEYS
    PCRPublicKey = PATH
    PCRCertificate = PATH
    Phases = PHASE-PATH…
    PolicyRef = STRING

with this change.

(cherry picked from commit ceca50d7a6f4c80a392b7e74aeb6b6cf11e58bf6)
2026-10-16 17:24:52 +01:00
Zbigniew Jędrzejewski-Szmek 9e3fbc386f bus-unit-util: fix return value for CPUAffinity=numa
sd_bus_message_append() returns 0 on success, but the convert helpers are
expected to return 1 when the assignment was handled. Returning 0 here was
harmless for callers that only check for errors, but it is inconsistent with
the other helpers and it would trip the new serialization test.

(cherry picked from commit 5b578462bc66795ea7f3a20ff1d21e0ae2afee28)
2026-10-16 17:24:52 +01:00
Zbigniew Jędrzejewski-Szmek ad0dde105c test-bus-unit-util: use an unconnected bus instead of connecting
The test only constructs messages locally and never sends them, so a real
connection is not needed. Create the bus with sd_bus_new() and fake the state,
like test-bus-util does, so that the test is never skipped when no bus is
available.

(cherry picked from commit 970993efbebb6a302417b593a3935f28bab7c192)
2026-10-16 17:24:52 +01:00
Ricardo Branco 2d3dd0a4fc seccomp: also refuse sched_setattr() in RestrictRealtime=
RestrictRealtime= only filtered sched_setscheduler(). sched_setattr()
can switch a task to SCHED_FIFO and SCHED_RR as well, and is the only
way to get SCHED_DEADLINE, so a process that is otherwise allowed to use
realtime scheduling (CAP_SYS_NICE, or a non-zero RLIMIT_RTPRIO) could
bypass the restriction.

The policy is passed in a struct sched_attr by pointer, which seccomp
cannot inspect, so refuse the syscall altogether. This also affects
non-realtime callers of sched_setattr() (nice, utilization clamps),
which now get the same error as the refused policies. Document this in
systemd.exec(5) and extend the test.

CPUSchedulingPolicy= is applied through sched_setattr(), so a service
manager running under RestrictRealtime=yes (e.g. in a container) could
no longer start units with a non-realtime policy. Fall back to
sched_setscheduler() on EPERM, which the filter still allows for these
policies. This is not possible with CPUSchedulingResetOnFork=yes, as the
filter refuses SCHED_RESET_ON_FORK too, so setting the policy still
fails in that case.

Signed-off-by: Ricardo Branco <rbranco@suse.de>
(cherry picked from commit 590ff29a641a4ddb736ea59303af9721fc6c1400)
2026-10-16 17:24:52 +01:00
Adrian Vovk 5e4d9b64f5 tests: Adapt to changes in varlinkctl's behavior
varlinkctl no longer stays silent if an object is empty, and that broke
some tests

(cherry picked from commit 8904b844a43e21530d82a39bbd51c3d9847e5426)
2026-10-16 17:24:52 +01:00
Adrian Vovk ffcf226c7f sd-varlink: Return empty object for missing params
Previously, sd-varlink was inconsistent about what it did with
empty/missing/null parameters in a Varlink call or reply: when
dispatching to a callback, it would always construct an empty object and
hand over the empty object to the handler (good!). But when returning
the value directly (i.e. with sd_varlink_call), it would return NULL
when parameters were omitted and a JSON null when the paramerters were
null.

This inconsistency is a violation of UAPI.20, which states that
receivers of Varlink messages MUST treat omitted/null/empty parameters
on Varlink calls and replies equivalently, where senders only SHOULD
prefer to omit the parameters.

This commit makes sd-varlink normalize the parameters to an empty object
whenever it is null or omitted, which brings sd-varlink into compliance
with this rule in UAPI.20

(cherry picked from commit 34db99971e728e2c4f155c01d43d24f3fe313bef)
2026-10-16 17:24:52 +01:00
Adrian Vovk adc93a4ad5 sd-json: Introduce SD_JSON_FORMAT_EMPTY_OBJECT
This mirrors SD_JSON_FORMAT_EMPTY_ARRAY

We also removed the assertion that a non-null variant is passed into
sd_json_variant_format. It _is_ actually valid to pass a null variant
through to sd_json_variant_dump. If neither SD_JSON_FORMAT_EMPTY_* flag
is set, then sd_json_variant_format will simply return an empty string.

The removal of the assertion fixes a crash in 'varlinkctl --exec call'

(cherry picked from commit 7e70352bf10c2fad0099f69e0c451ff1ce8dc362)
2026-10-16 17:24:52 +01:00
Achill Gilgenast 934e31fac0 locale-util: Update musl's default locale search paths
musl libc got a overhaul in it's locale support funded by NLnet,
as part the default search paths were set to search in
/etc/musl/locale, /usr/share/musl/locale, /share/musl/locale/.

Also change the behaviour on musl to search for multiple directories,
and include the old path as a fallback.

See https://www.openwall.com/lists/musl/2026/10/02/1

(cherry picked from commit 0f655ffc7b3318abae41869ca192e1817586a985)
2026-10-16 17:24:51 +01:00
Ivan Kruglov 3e39c54632 docs: clarify Varlink input and output policy
(cherry picked from commit 1c754bf06e1369c39abcff411a317a058e9b0b91)
2026-10-16 17:24:51 +01:00
Philip Withnall fa22119295 sysupdate: Ensure Context is offline by default
Since being online is a privileged operation, it’s better to fail-safe
and make the `Context` offline by default unless explicitly initialised
(e.g. with `context_from_cmdline()` or an explicit initialisation of
`.offline = false`).

There are a few instances where `.offline = true` is set explicitly.
I’ve left those in place, even though they’re now redundant, as
documentation.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
(cherry picked from commit 97183383af03279c43d9c270af5832d36d527d01)
2026-10-16 17:24:51 +01:00
Philip Withnall 2a40a1f313 sysupdate: Ensure internal helper contexts are run in offline mode
Currently, `CONTEXT_NULL` initialises `.offline` to false, so helper
contexts are being accidentally run in online mode. Fix that.

The following commit will rework this to be safe by default, but let’s
fix the individual instances first.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
(cherry picked from commit 4212fba4a4258a19057642d13a0ae52181675e23)
2026-10-16 17:24:51 +01:00
Philip Withnall 0450557040 test: Add a simple test for listing target versions in sysupdate
I’m about to refactor it slightly and it would be nice to have a little
test coverage to check against.

(cherry picked from commit 8433ed1c7a66ee575621cde027a890017769252c)
2026-10-16 17:24:51 +01:00
Ricardo Branco 399c086887 nspawn: mask socket() arguments to 32 bits in the NETLINK_AUDIT filter
The domain and protocol arguments of socket() are ints, but are passed
to the kernel in 64-bit registers, and the kernel truncates them to the
low 32 bits. The rule that makes socket(AF_NETLINK, *, NETLINK_AUDIT)
fail compared the full 64-bit registers with SCMP_CMP_EQ, so setting any
bit above bit 31 in either argument let an audit socket be created.

Use SCMP_CMP_MASKED_EQ with a 32-bit mask for both comparisons.

Follow-up for #44134

Signed-off-by: Ricardo Branco <rbranco@suse.de>
(cherry picked from commit 03e27922cae696af7a15b5375e1820e868284286)
2026-10-16 17:24:51 +01:00
Ricardo Branco 63051fa2bf seccomp: mask setns() nstype to 32 bits in RestrictNamespaces=
The nstype argument of setns() is an int, but it is passed to the kernel
in a 64-bit register, and the kernel truncates it to the low 32 bits.
The rule that blocks setns() with nstype == 0 compared the full 64-bit
register with SCMP_CMP_EQ, so setting any bit above bit 31 let the call
through, and the kernel then joined whichever namespace the fd referred
to, even one that RestrictNamespaces= is supposed to deny.

Use SCMP_CMP_MASKED_EQ with a 32-bit mask so we match on the same value
the kernel does.

Add a test that issues setns() via syscall() with an upper bit set.

Follow-up for #44134

Signed-off-by: Ricardo Branco <rbranco@suse.de>
(cherry picked from commit da72537164910f9050793055fef030711c00b954)
2026-10-16 17:24:51 +01:00
Ricardo Branco f190b1a631 seccomp: mask socket() domain to 32 bits in RestrictAddressFamilies=
The domain argument of socket() is an int, but it is passed to the kernel
in a 64-bit register, and the kernel truncates it to the low 32 bits.
The deny-list rules we install compared the full 64-bit register with
SCMP_CMP_EQ, so setting any bit above bit 31 (e.g. AF_VSOCK | 1UL << 32)
let a denied family through unfiltered.

Use SCMP_CMP_MASKED_EQ with a 32-bit mask so we match on the same value
the kernel does.

The allow-list path is not affected: it relies on the LT/GT range checks,
which compare as unsigned 64-bit, so values with upper bits set are
always rejected.

Add a test that issues socket() via syscall() with an upper bit set.

Fixes: #44134

Signed-off-by: Ricardo Branco <rbranco@suse.de>
(cherry picked from commit 62eb6cd8eab6a35a408b2c6547526645bda55ffa)
2026-10-16 17:24:51 +01:00
Armaan Sandhu 559c4bfdc0 journal-file: refuse hash chains and field lists that loop back
Data and field objects are only ever appended, and a new object is
always linked after the current tail of its hash chain, so a valid
next_hash_offset is either 0 or larger than the offset of the object
itself. A new data object is also prepended to the list of data objects
of its field, so a valid next_field_offset is always smaller than the
offset of the object itself. Nothing checks either of these when an
object is read, so if a chain loops back on itself, everything that
walks it loops forever:

- "journalctl --verify" spins in data_object_in_hash_table() instead of
  reporting the file as corrupted,
- journal_file_punch_holes() never returns when the file is archived,
  so it is never offlined,
- sd_journal_enumerate_fields() returns the same field over and over,
  so "journalctl --fields" never finishes,
- sd_journal_enumerate_unique() returns the same value over and over,
  so "journalctl -F FIELD" never finishes.

A single flipped bit in next_hash_offset or next_field_offset is enough
for any of these.

Check both in check_object(), like we already do for
next_entry_array_offset, so that all readers are covered.

(cherry picked from commit a1bf29afbeed5e4c702f58ea5a9038e433c99c11)
2026-10-16 17:24:51 +01:00
Lennart Poettering 1d40ff7a67 TEST-70-TPM2: skip pcrlock subtest if firmware TPM2 support is not available
Since a couple of days the pcrlock subtest fails intermittently on
debian-testing and arch CI runs (unrelated PRs: #44152 and others), with
"systemd-pcrlock is-supported" printing "partial" and exiting with 97,
i.e. TPM2_SUPPORT_FIRMWARE is missing.

The console output of the affected boots shows that the TPM already
breaks down while the firmware runs:

    EFI stub: WARNING: Failed to measure data for event 1: 0x8000000000000007
    EFI stub: WARNING: Failed to measure data for event 0: 0x8000000000000007

i.e. the TCG2 protocol is there, but all measurements fail with
EFI_DEVICE_ERROR, systemd-stub reports no active PCR banks in
LoaderTpm2ActivePcrBanks, and ConditionSecurity=measured-os is hence
false for the whole boot. pcrlock can't do anything useful in that case,
so let's skip the subtest instead of failing, and log what
"systemd-analyze has-tpm2" reports so that this remains visible.

(cherry picked from commit 09fdbf4d715e962cc13fd678760754e59d0aeeaf)
2026-10-16 17:24:51 +01:00
Daniel Sedlak d4da50bbc9 man: document that '+' prefixed commands ignore limit settings
(cherry picked from commit e8e4a385b9bf3a556e60131bef418ca89371bac1)
2026-10-16 17:24:51 +01:00
Nick c918ac7401 tmpfiles: do not fail --clean when a file disappears during cleanup
dir_cleanup() stores the result of xstatx_full() in r, which is also the
function's return value. If a file is removed between readdir() and
statx(), it is skipped, but when it was the last entry r stays -ENOENT
and --clean fails with EX_CANTCREAT without logging anything. A
successful statx() also overwrote errors recorded for earlier entries.

Use a separate variable for the statx() result.

Reproducer:
  d=$(mktemp -d)
  echo "d $d - - - 1d" >$d.conf
  while :; do touch $d/f{1..200}; rm -f $d/f*; done &
  for i in $(seq 200); do systemd-tmpfiles --clean $d.conf; echo $?; done | sort | uniq -c
  kill %1

Before:
    177 0
     23 73

After:
    200 0

Follow-up for a98a6eb95c.
Follow-up for 10072d8be4.

(cherry picked from commit 4c250e3f1325f91cdee047f7daeaf532abe4af6f)
2026-10-16 17:24:51 +01:00
Skye Soss 5cfe544a1a namespace-util: don't require privileges when there's nothing to enter
When namespace_enter_full() is called with namespaces that the current
process is already a part of, skip the setns() call on the user
namespace. This allows the function to succeed without CAP_SYS_ADMIN.

Follow-up for 211c3c9d41

(cherry picked from commit 27b1fd3a1e2e6c28bb09ec79cb3dc949a4ba416d)
2026-10-16 17:24:51 +01:00
Adrian Reber 75b8c3eff1 tpm2-util: refuse tokens with public key policy reference but no key
tpm2_parse_luks2_json() only insists on "tpm2_pubkey" being present when
"tpm2_pubkey_pcrs" is set, but happily accepts a token carrying
"tpm2_pubkey_ref" without a public key. tpm2_unseal() then trips over its
assert(!pubkey_policy_ref || iovec_is_set(pubkey)), i.e. a crafted LUKS2
header aborts whatever tries to unlock it instead of being rejected.

tpm2_make_luks2_json() never writes that combination (it asserts the same
invariant), hence refuse it when parsing, as is already done for a PCR
mask without a public key. This matters more now that systemd-dissect,
systemd-nspawn and systemd-sysext unlock images via these tokens, as the
headers they see are less trusted than the host's own volumes.

(cherry picked from commit 3520b44f7e398f924c267ee4527941924297c6bc)
2026-10-16 17:24:51 +01:00
Egor Ignatov 91c316859d vconsole-setup: skip font setup on a KD_GRAPHICS vc instead of failing
Since 7da67c3f8b ("vconsole-setup: skip setfont(8) when the console
driver lacks font support") font_load_and_wait() probes the font with
KDFONTOP before running setfont(8). The kernel returns EINVAL for a vc
that is not in KD_TEXT, which is not treated as "no font support", so
systemd-vconsole-setup now fails with

  Failed to check '/dev/tty1' has font support: Invalid argument

when run on an explicitly specified vc that a graphical splash (e.g.
plymouth) occupies, for instance from a unit ordered after getty@tty1.
Previously setfont(8) silently ignored this case: verify_source_vc()
accepts it with a notice that the font settings likely won't be applied,
and setup_remaining_vcs() skips such vcs. Do the same here, skip the
font setup and still load the keymap.

(cherry picked from commit 4a3ece0b733d41eab9baad25648c8a921c590ed2)
2026-10-16 17:24:51 +01:00
Siteshwar Vashisht 8e48f9c635 oci-util: add tests for oci_ref_parse()
(cherry picked from commit f891713c9487c29ec5b296568571974494ebe459)
2026-10-16 17:24:51 +01:00
Siteshwar Vashisht 7263fcf35f oci-util: don't mistake a registry port for an OCI tag
The tag separator can only appear as the last path component, hence
start the search there.

Fixes an issue reproducible through:

```
> /usr/lib/systemd/systemd-pull oci quay.io:443/fedora/fedora fedora-without-tag
OCI ref 'quay.io:443/fedora/fedora' is invalid.
```

(cherry picked from commit fe9fe613d92f2acffdf3f8b96d3af027f19d6b7e)
2026-10-16 17:24:51 +01:00
lucia-huang7 3b1c9a13df userdb: filter both keys in membership queries
GetMemberships with both keys only filtered groupName and could return
other members.

Reproduce with a non-member and a group that has members:
  varlinkctl call --more SOCKET io.systemd.UserDatabase.GetMemberships
    '{"userName":"nonmember","groupName":"GROUP","service":"io.systemd.Multiplexer"}'

(cherry picked from commit 2126abeb6d4905f95b963c7f5c5bc4bd92444ba5)
2026-10-16 17:24:51 +01:00
xinlongchen bc171ac92e sd-event: fix hang after ratelimit expiry
If sources are already pending, sd_event_prepare() calls
sd_event_wait(e, 0). Since fd69f22475 this returns 0 when a ratelimit
expiry callback was invoked, so that sources re-enabled by the callback
are evaluated in the next iteration. However, sd_event_prepare() then
returned 0 ("nothing pending"), so sd_event_run() blocked in epoll_wait()
forever, as the pending sources never make the epoll fd readable.

PID 1 can hit this via the ratelimited mount event source, which hangs
the boot, e.g. in the initrd after sysroot.mount.

Fix this by remembering in the sd_event object that a ratelimit expiry
callback was invoked in this iteration. In that case sd_event_wait()
reports the loop as pending, and sd_event_dispatch() returns right away
without dispatching anything, so that the caller goes directly for
sd_event_prepare() again, and no other callback is dispatched in the
same iteration.

Add a test that reproduces the issue.

Follow-up for fd69f22475.
Fixes #44107

(cherry picked from commit 1a60b10de9e4a3fe59a2efa3c6a58fd72c305807)
2026-10-16 17:24:51 +01:00
Paul Meyer 3a0ad99243 tpm2-util: look up existing NvPCR index before defining it
NvPCRs persist across boots, so on almost every boot NV_DefineSpace()
failed with TPM2_RC_NV_DEFINED before we fell back to reusing the
index, and the TSS logged that as an error. Check for an existing
index first and only define a new one if there is none.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
(cherry picked from commit 3c59c8daec12c445f446237c260594e4f5eb6b34)
2026-10-16 17:24:51 +01:00
Paul Meyer b59d59d71c tpm2-util: decouple NvPCR write policy from PolicyAuthorize
Pass the digest of the init branch to the NvPCR define and write policy
helpers instead of the PCR public key and policy ref, bundle what is
needed to satisfy the init branch into a struct, and split opening the
write session into an init and an extend variant. No functional change.

This prepares for supporting a second kind of init policy.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
(cherry picked from commit 13c417c1faa372a5c7f32d01385f741bc6e5cf57)
2026-10-16 17:24:51 +01:00
Lennart Poettering 42115775d2 report: bump default limits 4x
THe limits are hit with valid configurations, hence raise the limits
4x.

Fixes: #44125
(cherry picked from commit 116981d536f52279715df266098bf3093037fc3f)
2026-10-16 17:24:51 +01:00
Lennart Poettering 99a31af26e compress: don't treat Z_BUF_ERROR from inflate() as fatal
Since dac2b39405 ("compress: strictly check if stream finished on
decompress") the gzip branch of decompressor_push() no longer loops
"while (avail_in > 0)", but loops until inflate() can make no further
progress, so that we can properly detect truncated streams and trailing
garbage. This means inflate() may now be called with no input left.

If a previous iteration happened to fill the output buffer exactly
(avail_out == 0) while also consuming the last input byte (avail_in ==
0), we go around once more, and inflate() then has nothing to do and
returns Z_BUF_ERROR. This is documented zlib behaviour and not an error
condition: it merely indicates that no progress was possible. However,
we treated anything other than Z_OK/Z_STREAM_END as a corrupted stream
and returned -EBADMSG, hence valid gzip data was refused whenever the
input chunk boundaries happened to line up with the output buffer size
in this way.

Accept Z_BUF_ERROR if all input has been consumed, and let the existing
avail_in/avail_out check that follows decide whether we are done with
the current input, or whether the stream is truncated (in the size == 0
finalization case). If input is left, Z_BUF_ERROR still results in
-EBADMSG, so that we never loop forever without making progress.

Whether the boundary condition is hit depends on the data being
decompressed and on how it is chunked. This showed up in CI here:

https://github.com/systemd/systemd/actions/runs/38428217767/job/115403151687?pr=44163

Add a test that decompresses incompressible data split at every offset
around COMPRESS_PIPE_BUFFER_SIZE, which reliably triggers the condition
for gzip, and checks the other algorithms the same way for good measure.

Follow-up for: dac2b39405

(cherry picked from commit 4128feb9f29e01ccd1f6b7594acc4af579ba4534)
2026-10-16 17:24:51 +01:00
Chris Coulson b70a8580e2 tpm2-util: fix a duplicate event type name
EV_EFI_HANDOFF_TABLES and EV_EFI_HANDOFF_TABLES2 are both defined with
the same name.

(cherry picked from commit 195a17c59b22f5b0fa626fdb4917107cdc281bac)
2026-10-16 17:24:51 +01:00
Yu Watanabe ea94745010 TEST-82-SOFTREBOOT: also set and verify fdname
The order of fds in fdstore may not be preserved.
Set a name for the stored fd, then find the fd by name.

(cherry picked from commit b5372aef629c12266d9a87bafcb1192c697e5d86)
2026-10-16 17:24:51 +01:00
Yu Watanabe 5176a93218 fuzz-journald-stream: modernize code
- use ASSERT_OK() and friends,
- move variable declarations,
- add missing assertion for sd_event_run().

Fixes CID#1687042.

(cherry picked from commit fc8f6197a9b801e7b670e730a58490ef37075f0b)
2026-10-16 17:24:51 +01:00
Yu Watanabe d471026d72 TEST-58-REPART: use $ID_LIKE to check the os is Alpine or Nura
All other places use $ID_LIKE to detect Alpine/Nura.

(cherry picked from commit 0640dd91fca4f05ebfc22dcfb71c08cb5ef43c68)
2026-10-16 17:24:51 +01:00
Yu Watanabe 6f11f24642 test: silence more shellcheck warnings
(cherry picked from commit 89bddce9875de8ac5b18520cb771029b82b6c354)
2026-10-16 17:24:51 +01:00
Yu Watanabe 365cb58058 test: several fixlets for cleanup functions
- if 'set +e' is called in a trap (except for EXIT), then call
  'set -e' at the end.
- added several missing cleanups.

(cherry picked from commit a7de35462a3df6a30e7eba2d36d1b8bd2fd92aaf)
2026-10-16 17:24:51 +01:00
Alexandru N. Onea aa1ca34586 systemctl: subscribe to signals in is-system-running --wait
"systemctl is-system-running --wait" installs a match rule for the
StartupFinished signal, but never calls the manager's Subscribe()
method. PID 1 broadcasts manager signals unconditionally only on direct
(private) bus connections; on the API bus it emits them only while at
least one client is subscribed (see bus_foreach_bus()).

When run as non-root, systemctl talks to PID 1 via the system bus and
only receives StartupFinished if some unrelated client happens to be
subscribed at that moment. Otherwise it keeps waiting after boot has
completed, even though the system state is already "running" or
"degraded".

Call Subscribe() after installing the match and before querying the
current state, so the signal cannot be missed in between. This is a
no-op on direct connections, and the subscription is dropped
automatically when the connection closes.

Fixes: #44150
(cherry picked from commit 9ac5e0b4ee9e87d9ce671a70354dbab2b06c254b)
2026-10-16 17:24:51 +01:00
Yu Watanabe 37db22d38b man: fix function arguments for sd_bus_message_append_string_memfd() and friends
Then, added explanations for the missing arguments. Also mentioned that
the memfd is sealed by the function.

(cherry picked from commit 20604d980057da1a606339fb7a660242e8d2db02)
2026-10-16 17:24:51 +01:00
Yu Watanabe ea044bd514 sd-bus: do not fail if the passed memfd is already sealed
sd_bus_message_append_array_memfd() and
sd_bus_message_append_string_memfd() are public functions, hence the
passed fd may be already sealed by the caller. Let's gracefully handle
such case.

(cherry picked from commit 16025762d9055ec56694e4a1d74344029061b7c2)
2026-10-16 17:24:51 +01:00
Yu Watanabe b39f5cfa2e memfd-util: introduce memfd_set_sealed_gracefully()
(cherry picked from commit d2810b5c790e0a80f8fe1a68fa53054c34414b3d)
2026-10-16 17:24:51 +01:00
Yu Watanabe 9ad97c1f2e memfd-util: mention that F_SEAL_EXEC is supported since kernel v6.3
(cherry picked from commit f18365107051ce3b8c924f430a189ff027474e3b)
2026-10-16 17:24:51 +01:00
Yu Watanabe c31aa959f3 sd-bus: avoid overflow in sd_bus_message_append_{array,string}_memfd()
This also adds missing size == 0 check, and uses TAKE_FD().

(cherry picked from commit 9e84b6bea4156b8a417419730ff3a04c7e1e0375)
2026-10-16 17:24:51 +01:00
Yu Watanabe e8d4909b44 sd-bus: fix invalid fcntl() argument and error handling
Fixes 40164c2ceb.

(cherry picked from commit 4738dd120dcd4e7ee9c0bb825a41633aad15b0bd)
2026-10-16 17:24:51 +01:00
Yu Watanabe de6055cf6a fuzz: fix error handling of fcntl()
(cherry picked from commit 76f37fd835028177df93d674d9a2f897893af69c)
2026-10-16 17:24:51 +01:00
Yu Watanabe 96be8707ef udev-node: chase devlink on remove event
Previously, readlink_malloc() was used to find the target device.
However, devlink is a relative symbolic link, hence the path obtained by
readlink_malloc() never matched with the one by sd_device_get_devname().
Also path_startswith(target, "/dev/") was always negative.

Let's use chase_and_stat() to obtain the absolute path to the target
device that the devlink currently points to.

Fixes the following spurious logs on remove event:

(udev-worker)[2338]: loop1p1: Processing device (SEQNUM=2231, ACTION=remove)
(udev-worker)[2338]: Notify message sent to '@4814750286313953891': "INOTIFY_WATCH_REMOVE=1"
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/udevtest/x2' points to '../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/udevtest/x2', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-diskseq/9-part1' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-diskseq/9-part1', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-label/udevtest-b-fs1' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-label/udevtest-b-fs1', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-uuid/221d135f-7bf7-45b8-abeb-d9b3afb2c215' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-uuid/221d135f-7bf7-45b8-abeb-d9b3afb2c215', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-partlabel/udevtest-b-part1' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-partlabel/udevtest-b-part1', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/udevtest/b1' points to '../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/udevtest/b1', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/udevtest/x1' points to '../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/udevtest/x1', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-partuuid/5ef627b6-95f1-a942-8d7a-bd4ac53485ac' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-partuuid/5ef627b6-95f1-a942-8d7a-bd4ac53485ac', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/udevtest/b3' points to '../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/udevtest/b3', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-loop-inode/0:36-13-part1' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-loop-inode/0:36-13-part1', removing
(udev-worker)[2338]: loop1p1: Symbolic link '/dev/disk/by-loop-ref/\x2ftmp\x2fudevtest-b.img-part1' points to '../../loop1p1' which is outside of '/dev/', updating it.
(udev-worker)[2338]: loop1p1: No reference left for '/dev/disk/by-loop-ref/\x2ftmp\x2fudevtest-b.img-part1', removing
(udev-worker)[2338]: loop1p1: Device processed (SEQNUM=2231, ACTION=remove)

(cherry picked from commit 03a65741d77d61929b98977d1bfdf2b470e14b55)
2026-10-16 17:24:51 +01:00
Lennart Poettering 2c4e3b9a6b sysupdate: add PartitionZeroFill= and enable it by default for verity signature partitions
A verity signature partition carries a JSON object that must be followed by
NUL bytes only, up to the end of the partition (dissect refuses anything
else). The split-out artifact repart generates for it however is trimmed of
that padding since b54ef83414, so that it is a plain JSON text file (which
jq nowadays insists on).

sysupdate installs such a file into a partition by simply writing it at the
partition's offset, leaving whatever follows in place. Hence, once a shorter
signature (e.g. after rotating to a different key type) is installed into a
partition that previously held a longer one, the tail of the old signature
survives right after the new JSON object, and the partition becomes
unparsable.

Add a new PartitionZeroFill= boolean setting to the [Target] section, which
makes the importer continue writing zeroes up to the end of the partition
once the payload has been written, by passing --zero-fill= to systemd-import
and systemd-pull. It defaults to off, except for verity signature partitions
(which are tiny, hence this is cheap) where it defaults to on.

Fixes: #43567
(cherry picked from commit d3b6d765a5b320d6d864591c6a7b87e1047d0c78)
2026-10-16 17:24:51 +01:00
Lennart Poettering f9cfc019f9 import,pull: add --zero-fill= switch to fill up the destination range with zeroes
When writing a raw image into a section of an existing file or block device
(i.e. with --offset= and --size-max=, as sysupdate does when updating a
partition), we so far wrote precisely as many bytes as the payload was
large, leaving whatever followed in the destination range untouched. For
some payloads that's a problem: a verity signature partition for example
must carry NUL bytes only after the JSON object, and if a shorter signature
is written over a longer one, the tail of the old one survives.

Add a --zero-fill= boolean switch to both "systemd-import raw" and
"systemd-pull raw", which fills up the remainder of the destination range
(from the end of the payload up to --size-max=) with zeroes once the payload
has been written, via blockdev_zero_out(). It defaults to off, and requires
both --offset= and --size-max= to be specified.

(cherry picked from commit aff5aff407d421fbedc9eb0229c40996ca5570a1)
2026-10-16 17:24:51 +01:00
Lennart Poettering c4e7a0fdfe blockdev-util: add helper for zeroing out a range of a block device
blockdev_zero_out() overwrites a byte range of a block device (or a regular
file, e.g. a disk image) with zeroes. On block devices we try to let the
kernel do the work via BLKZEROOUT, which it might be able to offload to the
device. That ioctl operates on whole sectors only however, hence incomplete
sectors at the beginning and the end of the range are filled with explicit
zeroes, and only the aligned middle part is handed to the ioctl. If that
fails, explicit zeroes are written for that part too. On regular files a
hole is punched instead (which reads back as zeroes and keeps the file
sparse), falling back to explicit zeroes if the file system doesn't support
that.

(cherry picked from commit eb98b03118f27f33d3834ef8322f38391eb2c238)
2026-10-16 17:24:51 +01:00
Lennart Poettering 9752a9ef8f journald: refresh cached client context if stream's unit doesn't match
On kernels lacking CLONE_INTO_CGROUP sd-executor is forked into the
service manager's cgroup, logs a few messages from there, and only then
attaches itself to the unit's cgroup and connects stdout/stderr to
journald. Since we cache client metadata per PID and only refresh it
after 1s, log output on such a stream was attributed to init.scope
rather than to the unit, and hence "journalctl -u" (and thus
"systemd-run -v", "systemctl -v start", "systemctl -v wait") would not
show it.

Hence, if a stream tells us the unit it belongs to, and that doesn't
match what we have cached, refresh the cached data.

(cherry picked from commit 44a9316bf49967164567a7c716b79af7edf53d03)
2026-10-16 17:24:51 +01:00
Martin Pitt cb2f3814bb vmspawn: don't leak the job id if sending blockdev-create fails
The job map owns its keys, but the error path added in commit 1d0a8e5dbd
only frees the value when it unregisters the job. Free the key as well,
like dispatch_pending_job() does.

Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit 67b4f43a54f29b3c0fd5a455b4f956613eae8668)
2026-10-16 17:24:51 +01:00
Martin Pitt fddede73c7 vmspawn: stop the QMP pump on fatal errors
The next commit drains the QMP client before resuming the VM, while
boot-time devices are being set up. Callbacks report fatal setup errors
by logging them and requesting the event loop to exit. As the loop
isn't running yet, the pump would not notice and continue. Stop it
instead, and return the error.

Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit 50063acf50dc81b194780758d3cd2c5fb0a709f4)
2026-10-16 17:24:51 +01:00
Martin Pitt e4c45cae51 vmspawn: factor out the synchronous QMP pump
The upcoming boot-time device setup will need the same synchronous
driving of the QMP client before resuming the VM.

Move the loop into a helper, and generalize the error messages.

Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit 73833bdddfd4e8a1aa003516a8eda53515c9110f)
2026-10-16 17:24:51 +01:00
Martin Pitt ad0f1d66f2 vmspawn: log failures to dismiss completed QMP jobs
Most errors that end the event loop are logged where they happen, except
these two.

Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit 7681db4546d0eb3ef9160e90200ccaf5c9d7edc2)
2026-10-16 17:24:51 +01:00
Martin Pitt 8b54adc7c4 vmspawn: make the QMP job continuation machinery private
Since the previous commit, pending jobs are registered and dispatched
only within vmspawn-qmp.c. Move their types and helpers out of the
header.

No behaviour change, clean code move.

Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit f1a83ef728923f1cb527724581872d4ae5daf8fc)
2026-10-16 17:24:51 +01:00
Martin Pitt f3f8a96a82 vmspawn: dispatch QMP events in the bridge
The QMP client's userdata (the `VmspawnQmpBridge`, vmspawn's QPM state)
and its event callback were previously only set up in
`vmspawn_varlink_setup()`, after the VM has been resumed. This caused two
problems:

 - Boot-time device setup could not wait for its own completion before
   the VM is resumed, as that needs exactly these replies and events.

 - QMP replies and events that arrive before that were mishandled.
   Command callbacks like `on_qmp_complete()` crashed on a NULL bridge
   assertion. Also, `JOB_STATUS_CHANGE` events were dropped: they drive
   the boot-time blockdev-create continuation for `--ephemeral`.

   This only showed when the varlink setup failed, e.g. with a too long
   runtime directory path. Tearing down the bridge then failed the
   pending commands, and vmspawn aborted with an assertion instead of
   exiting with the error.

Both were introduced with commits 882049362d and 1a7b6fd9dd.

To fix this, set the `userdata` and bind the event callback when
creating the bridge. The bridge itself handles the events that drive its
own state (job continuations, `DEVICE_DELETED`), and forwards the others
to a callback that the varlink server binds for its event subscribers.

Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit 2cac293064215d3e4f5ed92a1e898f89e6ac4629)
2026-10-16 17:24:51 +01:00
Yu Watanabe d2b81326ac sd-device: seal object earlier
Previously, the sd_device object was sealed after it was verified. However,
the verifier device_verify() calls device_in_subsystem() which reads the uevent
file if the object is not sealed. Hence, basic information such as
MAJOR=/MINOR=/IFINDEX= and so on were updated by the uevent file,
and the ones passed through netlink were simply discarded.

Seal the device earlier, like we already do in device_clone_with_db().
This ensures all basic information passed through netlink is always honored.

Fixes the following issue:

$ journalctl --no-hostname --file TEST-17-UDEV.journal SEQNUM=2244 DEVNUM=259:1
Oct 12 04:44:22 systemd-udevd[404]: loop1p1: Device is queued (SEQNUM=2244, ACTION=remove)

$ journalctl --no-hostname --file TEST-17-UDEV.journal SEQNUM=2244 DEVNUM=259:2
Oct 12 04:44:22 (udev-worker)[2593]: loop1p1: Processing device (SEQNUM=2244, ACTION=remove)
Oct 12 04:44:22 (udev-worker)[2593]: Notify message sent to '@4814750286313953891': "INOTIFY_WATCH_REMOVE=1"
Oct 12 04:44:22 (udev-worker)[2593]: loop1p1: Device processed (SEQNUM=2244, ACTION=remove)
Oct 12 04:44:22 (udev-worker)[2593]: loop1p1: sd-device-monitor(worker): Passed 325 byte to netlink monitor.
Oct 12 04:44:22 (udev-worker)[2593]: Notify message sent to '@4814750286313953891': "PROCESSED=1"

Here, the main process of udevd receives the uevent with SEQNUM=2244 with
MAJOR=259 and MINOR=1. However, when it is forwarded to the udev worker,
MINOR= is changed to 2. Hence, the worker tries to read a wrong
non-existent database file and cannot remove stale devlinks.

Fixes a regression in ab1bd9daed.

(cherry picked from commit f58a2efc557a740891c5a56c82c971ae9a4e84c1)
2026-10-16 17:24:51 +01:00
Chris Coulson 81795d8826 tpm2: Don't fail NvPCR initialization if there is no initial write policy available
Currently systemd-tpm2-setup will fail if NvPCR initialization doesn't
succeed, either because the currently booted UKI carries no PCR public
key, or it carries no appropriate signed policy (one with the "initrd"
policy reference). In addition to this, systemd-pcrextend will
subsequently fail because it also fails to initialize the NvPCR it is
requested to extend.

This makes systemd-tpm2-setup return EX_CONFIG in these scenarios, with
this marked as a successful exit status in the service unit file. In
addition to this, systemd-pcrextend is updated to only attempt NvPCR
initialization from the initrd (the only place it will succceed), and
when called with --graceful, to not exit with an error code if the
target NvPCR is uninitialized, and can't be initialized because of a
missing PCR public key or appropriate signed policy. When called via
Varlink, it will return the existing "NoSuchNvPCR" error.

Note that I also removed some NvPCR initialization specific exit status
codes from systemd-tpm2-setup.service.in, as these can only be returned
via systemd-tpm2-setup-early.service.

This should address the issues in
https://github.com/systemd/systemd/issues/43848.

(cherry picked from commit e846bbad04d87e58ba9c3e30d8a1087141691715)
2026-10-16 17:24:51 +01:00
Daan De Meyer ef565d78af tree-wide: use pwrite_full() for positioned writes
Several places write a buffer at an offset with a single pwrite() or
pwritev(), and fail if the call writes less than the whole buffer. The
lock file of a dynamic user is then truncated to the bytes written, so
it keeps a cut-off user name. memfd_new_and_seal() fails for data larger
than one write() call accepts, which is about 2 GiB on Linux. The other
callers return -EIO, and lose the error that another write would report,
such as ENOSPC.

Use pwrite_full(), which keeps writing until the whole buffer is written
or a write fails. The lock file of a dynamic user is written from two
buffers and uses pwritev_full() instead.

repart writes the verity signature with lseek() and loop_write(). It
uses pwrite_full() as well, which does not move the file offset.

(cherry picked from commit 2fd17cb9eaca00a4dcb9af85a1f485e6d04bda04)
2026-10-16 17:24:51 +01:00
Daan De Meyer 8b9fb1bbec io-util: add pwritev_full() and pwrite_full()
loop_write() writes one buffer at the file position. To write at an
offset, callers call pwrite() or pwritev() directly and handle short
writes themselves.

Add pwritev_full(), which writes all iovecs at an offset, retries on
EINTR and short writes, splits batches larger than IOV_MAX, and reports
the number of bytes written, also on failure. Add pwrite_full(), which
does the same for one buffer.

(cherry picked from commit 4d36be491a568180dc6336b91b0c496bb8cb6601)
2026-10-16 17:24:51 +01:00
Daan De Meyer fcaf217ab2 journal: reset the offline state if blocking signals fails
journal_file_set_offline() sets OFFLINE_SYNCING before it starts the
offline thread. If the first pthread_sigmask() fails, it returns without
starting the thread and leaves the state at OFFLINE_SYNCING. The next
journal_file_set_offline_thread_join() then calls pthread_join() on a
thread that was never created.

Set OFFLINE_JOINED, as the error path of pthread_create() does.

(cherry picked from commit db2b225a30da26d0939f1f6d6c4b524bd2240900)
2026-10-16 17:24:51 +01:00
Florian Franzen e5197414d9 test: cover case folding of Type #2 entry IDs in TEST-86
Rename the UKI to a mixed case file name with a boot counter before
selecting the first profile, and give the second profile a mixed case
ID, so that both are only reachable if systemd-boot folds the entry IDs
of Type #2 entries with boot counter and of secondary profiles.

The entry IDs passed to bootctl set-default are spelled lower case and
without the counter, like loader.conf(5) documents and bootctl list
shows them.

(cherry picked from commit 3937823293b354d1a3f4a52ba14968eec7c42602)
2026-10-16 17:24:51 +01:00
Florian Franzen 2f53f23355 boot: case fold Type #2 entry IDs with boot counter or profile ID
config_find_entry() matches the case folded patterns from loader.conf and
the LoaderEntry* EFI variables against entry IDs with the case sensitive
efi_fnmatch(), relying on the IDs being lower case already. Type #1
entries fold their ID after the boot counter has been parsed, but Type #2
entries only did so when the file name carried no boot counter, because
boot_entry_parse_tries() rebuilds the ID from the original file name. The
ID of a secondary UKI profile was not folded either, as the profile ID
from the .profile section is appended verbatim.

Hence a UKI like EFI/Linux/Foo+3.efi, or a profile with ID=Profile1,
could never be selected via default, preferred, @saved, bootctl
set-default or systemctl reboot --boot-loader-entry=, while bootctl
(which matches case insensitively) claimed that it was the default.

Fold the ID unconditionally, like Type #1 entries do, and fold the
profile suffix as well. The file names used for renaming the boot
counter keep their case.

Follow-up for 4301ad00ef and
941b91600c.

(cherry picked from commit 1402519771a45745de3f6b7e93d08d7c96d3d65b)
2026-10-16 17:24:51 +01:00
Josh Hoffer 3e95f9bf08 test: add repart testcase for --size=auto with foreign partitions
Adding a partition with --size=auto to an image whose existing
partitions have no definitions used to hit
assert(!PARTITION_IS_FOREIGN(p)). Check that the existing partition
keeps its UUID and label and the new one is appended.

(cherry picked from commit ba56bc4376f24d52479fdf8153132f889a9b00b0)
2026-10-16 17:24:51 +01:00
Josh Hoffer 5fe12bc9de repart: keep foreign partitions' UUID and label across partition table reloads
With --size=auto, repart unloads and reloads the partition table after
context_acquire_partition_uuids_and_labels() ran. The reload recreates the
foreign partitions (those without a definition) with a null new UUID and
no new label, so context_mangle_partitions() sees them as changed and hits
assert(!PARTITION_IS_FOREIGN(p)) when adding a partition to an existing
image:

  Initializing UUID of existing partition 0.
  Setting partition label of existing partition 0.
  Assertion '!PARTITION_IS_FOREIGN(p)' failed.

Set the new UUID and label of a foreign partition when it is loaded, so a
reload keeps them.

(cherry picked from commit 4fc4f6bac772ff3749ba7e0bbcd607175694420c)
2026-10-16 17:24:51 +01:00
Reilly Brogan b2c8372d32 nss-systemd: copy PASSWORD_SEE_SHADOW into the group record buffer
nss_pack_group_record() left gr_passwd pointing at PASSWORD_SEE_SHADOW,
which is part of the module's read-only .rodata. That breaks callers that
modify the returned group before freeing it, in particular
pam_modutil_cleanup_group(), which zeroes gr_passwd when the PAM handle
is torn down and then segfaults on read-only memory.

Copy the placeholder into the caller-provided buffer, as
nss_pack_user_record() already does.

(cherry picked from commit c7a8e871de3427cf654d9a608dc58663874197bb)
2026-10-16 17:24:51 +01:00
Yu Watanabe a70dbe88d4 udev: close inotify fd after disabling the corresponding event source
The event source should be already disabled in manager_exit(),
but for safety.

(cherry picked from commit 02c1be8faf601ec374572446c55c8c5152810fe3)
2026-10-16 17:24:51 +01:00
Yu Watanabe 53eb316e26 TEST-17-UDEV: fix the device watch test
- Match the watch rules against the root block device's kernel name instead
  of a hard-coded 'sda', which is not portable (e.g. 'vda' on virtio).
- The nowatch check used 'test ! -e', but the watch symlinks form a
  bidirectional (circular) pair (ID -> wd -> ID), so dereferencing them with
  -e always fails with ELOOP and 'test ! -e' always succeeds, regardless of
  whether the watch is still present. Use '(! test -L ...)', which does not
  dereference the symlink.
- Drop never worked checks for the 1st and 2nd invocations.
- Drop unnecessary 'function' keyword.
- Drop unnecessary 00-debug.rules.
- Fix broken drop-in config file.
- Restart udevd after the drop-in config file.
- Trigger block devices after rules change to restore the original watches.
- Also verify that the device's inode is listed in the inotify fd's fdinfo.

(cherry picked from commit 8bcd2c8ee03b16ed84b5f5554c02a3bf2e900587)
2026-10-16 17:24:51 +01:00
Lennart Poettering b17f8cd9cc man: explicitly say the NSS is not OK in generators
Inspired by: #44112

(cherry picked from commit 54b24a3855de37e5e19235c44acd113eb6ce6830)
2026-10-16 17:24:51 +01:00
Daan De Meyer d5999b66a2 sbsign: name the input file when hashing it fails
verb_sign() logs argv[0], which is the verb, as the name of the file it
could not hash. Log argv[1], the input file.

(cherry picked from commit 9030bbfc90c646b7c07bbe8d70cfe7ba40b5a25a)
2026-10-16 17:24:51 +01:00
Daan De Meyer cec20dc153 kernel-image: handle errors when reading the .osrel section
uki_read_pretty_name() only handles a missing .osrel section. Any other
error, for example an .osrel section larger than PE_SECTION_READ_MAX,
passes a NULL buffer to parse_env_data(), and "bootctl kernel-inspect"
aborts:

    Assertion 'data' failed at src/basic/env-file.c:429

Return the error instead.

(cherry picked from commit 37717744394b433eb452674f060a4288a8f469bf)
2026-10-16 17:24:51 +01:00
Daan De Meyer 762840e4e0 pe-binary: only read the raw data of a section
pe_read_section_data() reads VirtualSize bytes starting at
PointerToRawData. When VirtualSize is larger than SizeOfRawData, because
the section ends with zero-initialized data, it returns the start of the
next section, or fails with EBADMSG at the end of the file. Read
MIN(VirtualSize, SizeOfRawData) bytes, like systemd-stub and uki_hash()
do.

(cherry picked from commit f219e7e790ec7b1064b71173ad697f48a5d71830)
2026-10-16 17:24:51 +01:00
Daan De Meyer 6f076ff729 pe-binary: add pe_load_headers_and_sections()
Most callers load the PE headers and the section table together, and
only keep the DOS header to pass it to pe_load_sections(). Add a helper
that does both, and use it instead of the private copy in bootspec.c.

(cherry picked from commit 5902fb429f52d75e7b25e6dea4be113e769b2ff8)
2026-10-16 17:24:51 +01:00
Daan De Meyer 899a314271 meson: define EFI_MACHINE_TYPE_NAME when the bootloader is disabled
EFI_MACHINE_TYPE_NAME is empty when systemd-boot is not built. Then
get_efi_arch() returns an empty string, and "bootctl
--print-efi-architecture" prints an empty line. The architecture does not
depend on whether systemd-boot is built, so always set the macro from
efi_arch.

(cherry picked from commit 7d3ca0a8c530ebb71a40298df6c5d4f88b37d7e9)
2026-10-16 17:24:51 +01:00
venkatchalla06 a77d9ebc58 firstboot: fix use-after-free/double-free of the Varlink reply in process_hostname()
ret_parameters (and ret_error_id) returned by sd_varlink_call()/
sd_varlink_callbo() are borrowed from the connection, as documented in
sd-varlink.h, and must not be unreffed by the caller. process_hostname()
declared its reply as _cleanup_(sd_json_variant_unrefp), freeing memory
owned by the Varlink connection and leading to a use-after-free/
double-free (the same bug class and ownership mistake just fixed for
pcrextend_pcr_now()/pcrextend_nvpcr_now() in 76a6dc6d).

(cherry picked from commit c556722826c4892939d2a6239ab00d0a343530a8)
2026-10-16 17:24:51 +01:00
abdurrafay3 088a53dea7 shutdown: copy shutdown verb so shutdown scripts receive $1
The arg_verb was copying the pointer to the shutdown verb, but that
pointer was being overwritten. When the shutdown scripts run, the forked
child calls rename_process() which overwrites argv, so the scripts got
an empty $1 instead of reboot, poweroff, etc.

Make a copy of the verb with strdup() so it is not affected.

Fixes: #44087

Follow-up for: 4927588993

(cherry picked from commit e6b62f2b3a564fcfb282dc4729eb9a5565e87ba9)
2026-10-16 17:24:51 +01:00
Lennart Poettering aaf399e797 sysinstall: fix typo in varlink iface
This is strictly speaking an API break, but given this is output only
and the component so new, I think we should just fix this anyway.

Fix: #44088
(cherry picked from commit fd309374687070ea1ef957d35dffe1e43b4a9c73)
2026-10-16 17:24:51 +01:00
Yu Watanabe 22880ff01c sd-event: coding style fix
(cherry picked from commit c33c5f91dba9bc59c40a227c2a0c728f96a17089)
2026-10-16 17:24:50 +01:00
Yu Watanabe 257d11c731 test: add test case for sd_event_add_inotify() with floating event source
(cherry picked from commit e1514ac3b9a249e08260b895fb64fd919dcc40b0)
2026-10-16 17:24:50 +01:00
Yu Watanabe a32b34813e sd-event: make inotify event source floating if ret is NULL
Otherwise, if sd_event_add_inotify() is called with NULL for ret,
the event source is disabled and never triggered.

Fixes a bug introduced by e67d738a87.

(cherry picked from commit 0582f7cba907eba6d55b686028d145061c38d0b7)
2026-10-16 17:24:50 +01:00
Lennart Poettering 275bae99e3 pretty-print: some more gcc appeasement
(cherry picked from commit b8ac543706cdf3c1c0872889098d171a5774775a)
2026-10-16 17:24:50 +01:00
Egor Ignatov 7476fff8f2 resolve: get the current DNS server before passing the server lists
manager_get_dns_server() may re-read /etc/resolv.conf and replace
m->dns_servers and m->search_domains, but it was passed as an argument
to dns_configuration_json_append() together with those lists, and the
order of evaluation of the arguments is unspecified. gcc with LTO reads
the list heads first, so after a foreign /etc/resolv.conf has changed
the freed lists are walked. Typically the serialization then fails with
EUCLEAN, which makes the SubscribeDNSConfiguration method of
io.systemd.Resolve.Monitor and in turn systemd-networkd-wait-online
--dns fail.

Call manager_get_dns_server() first and store the result in a local
variable.

(cherry picked from commit 04567a3b5e2e29a2252e89be8a3c625c692103d3)
2026-10-16 17:24:50 +01:00
Lennart Poettering c3e01464e7 test-parse-helpers: use ASSERT_STREQ()/ASSERT_EQ() in test_path_simplify_and_warn_one()
Tests exist to test stuff, hence we should not use plain assert(), but
the ASSERT_XYZ() macros, which are never compiled out and print useful
information on failure.

(cherry picked from commit 13bf80491bcf8ffee2b43cf86b16e3d1394300ef)
2026-10-16 17:24:50 +01:00
Lennart Poettering afb572f06e bus-message-util: initialize variables to make gcc happy
gcc 13 on armhf complains with -Wmaybe-uninitialized about family, port
and server_name in bus_message_read_dns_array(), even though they are
always set when bus_message_read_dns_one() returns > 0.

(cherry picked from commit da4052d0037c6bb4981387bb375355f595ab4b1c)
2026-10-16 17:24:50 +01:00
Lennart Poettering 8334118621 test-resolved-packet: use assert_se() for the string comparison
With assert() the comparison is compiled out in NDEBUG builds, leaving
twilio_reply_string unused, which breaks the build with -Werror.

(cherry picked from commit e1577aaed620793fdec39ded861b873e17627f46)
2026-10-16 17:24:50 +01:00
Lennart Poettering 7a45af6e89 test: silence SC2329 for trap-invoked cleanup() in TEST-17-UDEV.sanity-check
cleanup() is only called via 'trap cleanup EXIT', which newer shellcheck
versions report as SC2329 rather than SC2317. Disable both, like the other
test scripts do.

(cherry picked from commit e42ad4c3b60b9bedf59f03901c88062b67a8829d)
2026-10-16 17:24:50 +01:00
Lennart Poettering 686bf67609 test-sd-device: tolerate devices disappearing during enumeration test
On CI (Azure runners) the accelerated networking PCI VF behind the
Hyper-V vmbus PCI bridge may be hot-unplugged while the test runs,
causing sd_device_new_from_syspath() to fail with ENODEV for a device we
just enumerated:

  test_sd_device_one(/sys/devices/LNXSYSTM:00/.../pci7870:00/7870:00:00.0)
  Assertion failed: Expected "sd_device_new_from_syspath(&dev, syspath)"
  to succeed, but got error: -19/ENODEV

Skip devices whose syspath vanished since enumeration rather than
failing.

(cherry picked from commit b43136ffcdbd62b5d11c226df9dd33372cff7823)
2026-10-16 17:24:50 +01:00
Lennart Poettering 9b899b7938 metrics: lift restrictions on fields types
These checks stem from a rework from strv to a proper varlink object,
but the whole rework's point was to allow more expressive field types,
hence drop the unnecessary verification of the string type.

(cherry picked from commit fc38a61894bcc772b2bc8d56be9700335cdba181)
2026-10-16 17:24:50 +01:00
Yu Watanabe c20ee1bfc2 udev: raise priority of post event source above device monitor
The commit bca7d4ab23e90ec8859fbaeadaa5e0ae9e51b398 kept the priority of
the post event source at the default (NORMAL), which is lower than the
device monitor (EVENT_PRIORITY_DEVICE_MONITOR, NORMAL-1). Since a pending
device monitor is always dispatched first, on_post() only runs when the
monitor is not pending, hence the sd_event_source_get_pending() check
added in the previous commit could never be true. Moreover, during a
uevent flood on_post() is starved, and as it is the only caller of
event_queue_start(), idle workers no longer get events assigned.

Let's give the post event source a priority above the device monitor, but
below the worker event sources so that worker completions are observed
before the queue is started.

Also, similar to checking whether the device monitor event source is pending,
when synthesizing change uevents, new uevents may come soon. Do not remove
the queue file and do not kill idle workers in that case.

Follow-up for bca7d4ab23e90ec8859fbaeadaa5e0ae9e51b398.
Fixes #43865.

(cherry picked from commit a0d25767050d76cfbc1f32dcdde3a0c3da5a7423)
2026-10-16 17:24:50 +01:00
Jonghyun An 6eb23d3526 systemctl: quote command arguments in status output
The Process lines in systemctl status join argv with spaces, making
multi-word arguments ambiguous and empty arguments invisible.

Use quote_command_line() with SHELL_ESCAPE_EMPTY to retain argument
boundaries. Leave the formatted string NULL for an empty argv vector so
that strna() prints n/a. Cover whitespace, empty arguments and literal
dollar signs in TEST-26-SYSTEMCTL.

Fixes #43938.

(cherry picked from commit a83a0d2fc461091b16a699aeba07a82d71545c71)
2026-10-16 17:24:50 +01:00
Bertrand Jacquin 17f3e1fb3b dns-packet: only set mDNS cache-flush bit on mDNS packets
Since 748a548e1b ("resolved: set cache-flush bit on mDNS responses"),
every RR of an mDNS zone, except DNS-SD service enumeration PTRs,
carries DNS_ANSWER_CACHE_FLUSH, and dns_packet_append_key() turns it
into the cache-flush bit regardless of the protocol of the packet.

When a lookup via the DNS stub is answered from our own mDNS zone, e.g.
the reverse lookup of one of our link-local addresses, the RR is sent
with class 0x8001. In unicast DNS bit 15 is part of the class value, so
clients see CLASS32769 instead of IN:

  $ dig +nocmd +nocookie -x fe80::d1f:2970:a730:5ab8 @127.0.0.53
  ;; Warning: Message parser reports malformed message packet.
  ;; Got answer:
  ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30061
  ;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

  ;; OPT PSEUDOSECTION:
  ; EDNS: version: 0, flags:; udp: 65494
  ;; QUESTION SECTION:
  ;8.b.a.5.0.3.7.a.0.7.9.2.f.1.d.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa. IN PTR

  ;; ANSWER SECTION:
  8.b.a.5.0.3.7.a.0.7.9.2.f.1.d.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa. 120 CLASS32769 PTR lady-voodoo.local.

  ;; Query time: 1 msec
  ;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
  ;; WHEN: Wed Sep 02 21:40:55 IST 2026
  ;; MSG SIZE  rcvd: 132

The cache-flush bit is defined for mDNS only, hence only set it on mDNS
packets.

See: https://github.com/systemd/systemd/pull/43627
(cherry picked from commit 21159c052bbf28983115d842dbc2597869177d42)
2026-10-16 17:24:50 +01:00
Bertrand Jacquin f2de9253da dns-packet: only set mDNS cache-flush bit in responses
dns_packet_append_key() ORs MDNS_RR_CACHE_FLUSH_OR_QU into the CLASS
field of any RR whose answer item carries DNS_ANSWER_CACHE_FLUSH,
regardless of the packet the RR is appended to.

Since 748a548e1b ("resolved: set cache-flush bit on mDNS responses"),
every RR of an mDNS zone, except DNS-SD service enumeration PTRs,
carries that flag. The Authority Section of mDNS probes (RFC 6762,
section 8.2) is filled from our mDNS zone via dns_zone_lookup(), which
applies the flag to items still in probing state too, hence probes are
sent with class 0x8001 in their Authority Section.

RFC 6762, section 10.2, scopes the cache-flush bit to announcements and
responses. Peers ignore it for probe tiebreaking, so this is not an
interoperability issue, but there is no reason to set it there.

Only set the bit when the packet is a response. mDNS responses,
announcements and goodbye packets are all built by
dns_scope_make_reply_packet(), which sets QR before appending any RR, so
they keep the bit. The Known-Answer list of queries is unaffected, as it
is appended without flags already.

See: https://github.com/systemd/systemd/pull/43627
(cherry picked from commit 1c57b40fc1451b1f518e6168dbd28bf1e5fa2b4d)
2026-10-16 17:24:50 +01:00
Jörg Behrmann 03ae6cf3ce ukify: pack FWHEADERMAGIC directly instead of using bytes.fromhex
The current implementation

    FWHEADERMAGIC = 'feeddead'
    magic = bytes.fromhex(FWHEADERMAGIC)
    struct.pack('<p', magic)

returns a single null byte b'\x00', which is not equal to 0xfeeddead in any
endianness.

(cherry picked from commit fe689d2d7946593001bb3d0e32d51d694af5d50d)
2026-10-16 17:24:50 +01:00
Chris Down 3d7fd9fc37 TEST-03-JOBS: Test cancelling a job through private bus
(cherry picked from commit 32bf5695417d0bc01a42bfab2ff22ef0ddc7d533)
2026-10-16 17:24:50 +01:00
Chris Down bcd08128e4 core: Don't abort when canceling a job through the private bus
Messages on the private bus have no sender. As it is now, when a job is
canceled through it, as "systemctl cancel" does when run as root, we
pass a NULL name to sd_bus_track_contains(), which fails an
assert_return(). In developer builds, that makes PID 1 abort. Otherwise
it's only logged at debug level, and we consult polkit, as we should.

Let's only check whether the sender owns the job for messages on the API
bus. That's the only bus bus_job_track_sender() tracks senders on, so
jobs enqueued through the private bus aren't tracked anyway.

(cherry picked from commit bfeac4c30e1a818cda14c8d1b347d500a9dfe4e3)
2026-10-16 17:24:50 +01:00
Chris Down bceb7741b5 test: Cover BPF link replacement when re-realising cgroups
(cherry picked from commit 09d08b879986e9b55a4d1ed767d1e6b40ca82e39)
2026-10-16 17:24:50 +01:00
Chris Down 8ac16654bc core: Don't leak BPF links when realizing a cgroup again
cgroup_context_apply() attaches the BPF programs again whenever the
cgroup is realised again, for example, if someone does set-property or
daemon-relaod.

As it is now, their installers overwrite the links of the previous
installation without freeing them, so the previous programs stay
attached until the cgroup is removed, and keep enforcing whatever
settings they were loaded with.

For example, a unit with SocketBindDeny=any that is allowed to bind to a
port with "systemctl set-property foo.service SocketBindAllow=tcp:1234"
still cannot do so once its cgroup is realised again, as the previous
program keeps denying it. Whoops!

To fix this let's free the previous links once the new ones are
attached.

(cherry picked from commit 2f11fb19b7292339632e9b396fcab12729cde1ff)
2026-10-16 17:24:50 +01:00
Yu Watanabe 356b2edcc1 TEST-17-UDEV: drop redundant test cases
All test cases are covered by TEST-17-UDEV.device-unit-state-transition-netif.sh
added in the previous commit.

(cherry picked from commit 1ac7d20002fe6e94d24c1e652cdffa5515e1461e)
2026-10-16 17:24:50 +01:00
Yu Watanabe 8f20400e85 test: introduce several helper functions
(cherry picked from commit 04c4fe7930d83247b68427dd1cc61b19219596c2)
2026-10-16 11:36:33 +01:00
Yu Watanabe f85b6ddaae test: show name of failed test case
(cherry picked from commit 4ef7744c2e275bf6dd4199623aa7959f9f6551c8)
2026-10-16 11:36:33 +01:00
Jonghyun An 6f2b2f4df0 ukify: accept whitespace around commas in PCR bank and phase lists
Splitting on either a comma or whitespace produces empty items when
whitespace is adjacent to a comma. This rejects valid phase lists and leaves
empty entries in PCR bank lists.

Consume whitespace around commas and accept a single trailing comma in
both lists. Reject leading commas, empty entries between commas and
repeated trailing commas. Treat an empty PCR bank list as no banks.

Update the existing configuration test to cover whitespace around commas
and a trailing comma in both settings.

(cherry picked from commit 44cf775de15c1853c28fd2610f49014855ba09ec)
2026-10-16 11:36:33 +01:00
Nick Rosbrook 7457840e90 ssh-generator: do not log unusable CID
For consistency with ssh-issue output, do not log about the CID if it is
not a usable destination.

(cherry picked from commit 0d59bcb6944d1f34e8eca9208af198f5357e8535)
2026-10-16 11:36:33 +01:00
Nick Rosbrook fd34e93645 ssh-issue: never suggest connecting with VMADDR_CID_ANY
Even if the vsock driver allows using this as a wildcard to listen over
vsock, it still cannot be used as a destination CID from the host (and
is rejected by systemd-ssh-proxy). Show a more generic message in this
case instead.

Use VSOCK_CID_IS_REGULAR() to exclude other similar cases too.

Follow-up for 85afe8e82d.

Fixes: https://github.com/systemd/systemd/issues/43364
(cherry picked from commit affcccd4d07180b82d918c0c5f0601d1dec80946)
2026-10-16 11:36:33 +01:00
Dustin Kirkland f844429534 bootctl: don't fail 'status' when the ESP has no random seed
Since f90efd2d13 the result of the
access() check for loader/random-seed is stored in 'r', which is what
verb_status() returns. A missing seed file then makes 'bootctl status'
exit with 1 without logging anything, even though it's only reported as
"Exists: no". Use 'k' for the check, like the other informational
probes in this function.

(cherry picked from commit 05808e11b9399e6c2149f1f524b3282545ba7569)
2026-10-16 11:36:33 +01:00
Rodrigo Campos d6bf5fbaf2 test: cover attaching with a profile that does not exist
Both attach and reattach must fail, and the latter must not detach the
image first.

(cherry picked from commit 430f8962cf2e454cc9b474a22b92a89a26872e9b)
2026-10-16 11:36:33 +01:00
Rodrigo Campos 0b1c0782bb portablectl: quote the profile name in the validation error
With an empty profile we get:

	$ portablectl attach -p "" foo
	Unit profile name not valid:

It's not clear what is the profile. Let's quote it so it's clear also
for empty profile names.

(cherry picked from commit 6c8b21d30db4f4d5a0cdce9f2dc6a99b9b47e7c7)
2026-10-16 11:36:33 +01:00
Rodrigo Campos 92d54a0d3d portable: fail attach/reattach if the profile does not exist
Before this commit, if you attach a portable service using a profile
that doesn't exist, it just doesn't add the profile dropin and no
warning nor anything is shown:

	$ portablectl attach -p nonexistent xxx
	  (Matching unit files with prefix 'xxx'.)
	  Created directory /etc/systemd/system.attached.
	  Created directory /etc/systemd/system.attached/xxx-capsule.service.d.
	  Written /etc/systemd/system.attached/xxx-capsule.service.d/20-portable.conf.
	  Copied /etc/systemd/system.attached/xxx-capsule.service.
	  Created symlink /etc/portables/xxx.raw → /var/lib/portables/xxx.raw.

	$ ls /etc/systemd/system.attached/xxx-capsule.service.d/
	  20-portable.conf

The 10-profile.conf is not added.

If no profile is attached, the /run bind mount is not added and then lot
of things inside fail in ways that don't make sense.

This patch just makes portable_attach() and reattach check the profile
exists. If it doesn't exist, it shows this error now:

	# portablectl -p doesntexists reattach xxx
	(Matching unit files with prefix 'xxx'.)
	ReattachImage failed: Profile 'doesntexists' does not exist, refusing. (Available profiles are: default, nonetwork, strict, trusted)

In reattach we do it early, before detach, so we don't detach and then
fail to attach it and leave the service detached.

An empty profile name is rejected too by the call to
filename_is_valid(). portablectl already rejects empty profile names.

Please note that we don't change install_profile_dropin(), as that skips
non-existing profiles because that is done at the unit type level and
it's okay if it doesn't exist for some unit types. For example,
/usr/lib/systemd/portable/profile/trusted/ ships a service.conf, but not
timer.conf, socket.conf, etc.

(cherry picked from commit 5642eb3d848300f7225dff25fdd82940e55101c9)
2026-10-16 11:36:33 +01:00
Rodrigo Campos 2832b3f2c9 portable: log the right error when the profile lookup fails
find_portable_profile() returns a negative errno and does not set errno,
so the two log messages reported a stale or unrelated errno value.

(cherry picked from commit 8da05abc9a8c21af85542b0d4d1d5f48a47f738e)
2026-10-16 11:36:33 +01:00
Jörg Behrmann 04a645cce5 ukify: check terminal colour support more thoroughly
This adds an extended version of mkosi's terminal_is_dumb that checks that both
stdout and stderr are connected to a TTY and also checks that the TERM
environment variable is not set to dumb. Additionally this adds support for the
NO_COLOR variable.

(cherry picked from commit 2c46b11b319e42acb113f659098fad8eeac51b69)
2026-10-16 11:36:33 +01:00
vidir-semaphor afb890d5fc Fix apparent copy-past error in (un)lock-secureboot-policy entry
(cherry picked from commit 8e39ca4bfa6c77c8639bbeb89ec938e6e6683cec)
2026-10-16 11:36:33 +01:00
Ilya Naidanov f5ecd46e22 binfmt: clear the ignored flush failure before the registration loop
The "flush out all rules" step writes to /proc/sys/fs/binfmt_misc/status and
explicitly ignores failure, but it assigns the result to the same r that
RET_GATHER() consumes below. RET_GATHER() keeps the first error it is given,
so a failed flush is still returned from run() and systemd-binfmt exits 1 even
when every rule in binfmt.d was registered successfully.

Reset r after the ignored flush so it cannot be gathered.

Tested on WSL2 (kernel 6.18.40.1-microsoft-standard-WSL2), systemd 261, where
/proc/sys/fs/binfmt_misc/status is a read-only tmpfs. Before this, the binary
registered /etc/binfmt.d/nixos.conf successfully and then exited 1; after, it
exits 0. /proc/sys/fs/binfmt_misc/WSLInterop stays enabled in both cases.

Fixes #44035.

(cherry picked from commit 8fc6b2141b113f63427a766aa800539437138d6c)
2026-10-16 11:36:33 +01:00
Jonghyun An 1de356e556 man: document ukify SignInitrdPCRs setting
UKI/SignInitrdPCRs was added together with --sign-initrd-pcrs, but only
that command-line option is documented. Document the configuration key
and move the entry to the [UKI] section.

Fixes #43863.

(cherry picked from commit 4f8ca5032fd0633c6b5caff4868a375ac91b5b0f)
2026-10-16 11:36:33 +01:00
Daan De Meyer 121d621934 rpm: Fix copy paste bug in lua triggers
(cherry picked from commit df4eba96b645d1423b3b5d2090e720c2dc28c58b)
2026-10-16 11:36:33 +01:00
Daan De Meyer 4acbcd3302 nsresourced: keep running if the BPF-LSM programs cannot be attached
Since 7eb016d60b ("nsresourced: restore the BPF-LSM policy from the
registry on startup"), the programs are loaded in manager_setup_bpf()
but only attached later in manager_attach_bpf(). Before that, a failed
attach made the whole setup fail, and nsresourced proceeded with the
user namespace interfaces disabled. Now the same failure is fatal, and
nsresourced exits on kernels that can load BPF-LSM programs but not
attach them, such as arm64 before 7.2.

Handle a failed attach like a failed setup again: log it, drop the BPF
state, and continue with the user namespace interfaces disabled.

When a program fails to attach, the programs attached before it stay
attached, because userns_restrict_attach() has already pinned their
links. The programs keep enforcing the policy. Without the ring buffer
reader, nsresourced never reaps dead namespaces from the maps. Remove
the pins created by the failed attach, so that dropping the BPF state
detaches the programs.

test-userns-restrict fails on the same kernels, because it asserts that
the attach succeeds. Skip it instead.

Fixes: #43964
(cherry picked from commit 4446b9bb51c9900f22d7ba50379fa96dcbfb58f2)
2026-10-16 11:36:33 +01:00
Zbigniew Jędrzejewski-Szmek 58befb6079 man/systemd-vmspawn: consistently mark as experimental
It was added as experimental in v255: "this component is experimental and
its public interface is subject to change". This status was never changed
and the meson config still disables vmspawn by default in non-developer
builds. I think this makes sense to keep things this way and remove all
experimental markings at once with an official announcement once we're
sure about the interface.

(cherry picked from commit f2323da4da8c3311b855f505cdddc66400c501ee)
2026-10-16 11:36:33 +01:00
Zbigniew Jędrzejewski-Szmek 945e223a6c man: add a shared "experimental" blurb for features
(cherry picked from commit a6eb2b4d2e7f747bbfb0f5f3ebb1421855113d36)
2026-10-16 11:36:33 +01:00
Zbigniew Jędrzejewski-Szmek bc97e77ba7 man: reword "experimental" blurbs to be more accurate
The text implied that the changes may happen randomly at any time.
Obviously, they can only happen after an update, but also we're unlikely
to do that not on a major release boundary. So town down that part of the
message. At the same time, it's important that the change might just
happen. For stable features, we also sometimes implement incompatible
changes, but this is preceded by announcements and lengthy deprecation
periods. So use the phrase "without advance notice".

OTOH, the text implicitly promised future stabilization. This might or
might not happen, so remind the users that it might not.

(cherry picked from commit 96cb6a5c74c8cd64334c48ddcca18e128e9a40ea)
2026-10-16 11:36:33 +01:00
Zbigniew Jędrzejewski-Szmek d81edcf73d man: reuse the shared "experimental" blurbs
The blurbs were added to be shared, but no sharing was actually
done.

Also, rename "singular"/"plural" to "option"/"options", so that we
can later have "component"/"components" and possibly other
variants.

The text were a bit different in various places, but I don't think
it was a useful distinction.

(cherry picked from commit 69dd30fddf2bbf358e05a632b0ef3383eb46b028)
2026-10-16 11:36:33 +01:00
Jonghyun An 0236ab116e ukify: reject trailing garbage in output section specifications
The output section parser matches a valid prefix and ignores any remaining
characters. For example, '.cmdline:textjunk' is treated as text output,
and '.cmdline:text@' is accepted despite the missing output filename.

Require the complete specification to match the existing grammar, and
test malformed suffixes along with valid text and binary output.

(cherry picked from commit fbb4b64bdb326fac5c19122f88bd9d1feb0350e5)
2026-10-16 11:36:33 +01:00
Yu Watanabe 4aea5ef8e9 udev: lower priority of events triggered by device monitor
Commit 905a89a219 raised the priority of
events triggered by the device monitor, so that the queue file would not
be removed while the netlink socket in the device monitor still had a
queued uevent.

However, that causes a problem: when udevd receives a flood of uevents,
sigchld and notification events from the workers are postponed. As a
result, the queued events may not be processed during the flood, and
udevd's memory consumption keeps increasing.

Let's lower the priority of these events again. To avoid removing the
queue file while a uevent is still pending on the netlink socket, check
whether the event source corresponding to the device monitor is pending.

Follow-up for 905a89a219.
Fixes #43865.

(cherry picked from commit bca7d4ab23e90ec8859fbaeadaa5e0ae9e51b398)
2026-10-16 11:36:33 +01:00
Zbigniew Jędrzejewski-Szmek dfdcaaa269 meson: use -static-pie instead of -static in PIE mode
If compiling with -Db_pie=true, we should do PIE compilation (position
independent executables), even in the static mode.

The caveat is that people distributions actually override compilation
flags when doing their builds. They'll need to set the static flags
properly if they do such builds.

(cherry picked from commit 8b289a8c4d9e2f69a2c10d109c1c19f353005047)
2026-10-16 11:36:33 +01:00
Daan De Meyer b7ae93f093 stat-util: fix null_or_empty_path_with_root() below a root
null_or_empty_path_with_root() passes a path that already includes the root
to chase_and_stat() with CHASE_PREFIX_ROOT, so the root is added twice. It
also only recognizes /dev/null when the path itself is /dev/null. Below a
root, a symlink to an empty file therefore fails with ENOENT. A symlink to
/dev/null fails the same way when the image has no /dev/null. Resolve the
symlink inside the root without requiring the target to exist, and stat the
target through the O_PATH fd that chase() returns.

chase() accepts ret_fd together with CHASE_NONEXISTENT and sets the fd to
-EBADF when the target is missing. Its comment says that ret_fd cannot be
combined with CHASE_NONEXISTENT. Fix the comment.

(cherry picked from commit f2b0c29597466bdcc800dcfa8da4c8192fb9e824)
2026-10-16 11:36:33 +01:00
cksrb63 5f73eab263 docs: fix stale links
(cherry picked from commit 26bde2b760ade0f73d3fbe90d12a492c1a5348ba)
2026-10-16 11:36:33 +01:00
Jonghyun An db049fc898 ukify: include the invalid value in boolean errors
The invalid-boolean error contains a literal f-string prefix and
placeholder, hiding the value that failed to parse. Format the message
to include the rejected value.

(cherry picked from commit aeef38045e74dc585088a64c601166f989705d75)
2026-10-16 11:36:33 +01:00
Siteshwar Vashisht e9ba92f7f0 tpm2-util: TPM2_PCR_MASK_VALID() should take 64-bit parameter
... as some of the fields like `pcr_mask` field of `struct
tpm2_credential_header` that are passed to this function are 64-bit.

(cherry picked from commit de827820240d56a142aea7a2b012121a8869282d)
2026-10-16 11:36:33 +01:00
Siteshwar Vashisht 32cfe286c9 creds-util: fix validation check for TPM2 PCR mask
... field on big-endian architectures.

(cherry picked from commit 542c3cd97a7a1a7f4d29cec2afabc431be2d651e)
2026-10-16 11:36:32 +01:00
Siteshwar Vashisht 066824ae71 udev-rules: fix remaining buffer size calculation
... in `attr_subst_subdir()`.

`strnpcpy_full()` returns space left in the buffer. Its return value
should be directly used instead of being subtracted from buffer size.

(cherry picked from commit d5b4357f8f1829608b3a5b641bb97e480a45a2c3)
2026-10-16 11:36:32 +01:00
Siteshwar Vashisht 3e069f1c23 nspawn-bind-user: fix logging an error message
... in `write_membership()` function.

Log the actual error message returned from `chase_and_open()`.

(cherry picked from commit 513e4b9947c619e2ecfe79c0e81d6461dc65480c)
2026-10-16 11:36:32 +01:00
Siteshwar Vashisht 7d433629cf logind: fix one-byte buffer overflow
... in `inhibit_what_to_string()`.

Add missing colon with `handle-reboot-key`.

(cherry picked from commit 458c5ce35cf9c2057d4516b0298b83c84118b75d)
2026-10-16 11:36:32 +01:00
Siteshwar Vashisht ea634edbb5 core/dbus-unit: fix returning on "JobTimeoutUSec"
branch in `bus_unit_set_transient_property()`.

(cherry picked from commit 041e70d7f70372f06e1651a6f2dfd82fa2a13b8e)
2026-10-16 11:36:32 +01:00
Armaan Sandhu f41defc034 report: make report-files listing and lookup agree on masked entries
The metric list is built with conf_files_list_strv(), but each metric's
value is then looked up again by walking report_files_dirs[] by hand,
and the two disagreed whenever an earlier directory had an entry that is
not a regular file:

 - conf_files_list_strv() skipped such an entry and listed the one from
   a later directory, so the metric was advertised by Describe();
 - file_metric_generate() only moved on to the next directory on
   -ENOENT, so it hit the non-regular entry, logged a warning and
   produced nothing.

The practical case is masking a vendor-supplied entry with a symlink to
/dev/null: the metric kept being described, was never listed, and every
scrape logged "Failed to open ..., skipping: File descriptor in bad
state".

Honour masks in the enumeration via CONF_FILES_FILTER_MASKED_BY_SYMLINK,
as other conf dirs do, and make the lookup skip non-regular entries the
same way the enumeration does. Document the masking in the man page and
cover both cases in TEST-74-AUX-UTILS.report.

(cherry picked from commit 08be8677539642f45c6127085283cf08b6a410b7)
2026-10-16 11:36:32 +01:00
flixman f9b52a6be3 Implement fallback for cmdline in ukify installation
Added fallback for cmdline if not provided in config.

(cherry picked from commit 1e098a4b34c68e9b1878efb9d7c1b56a2c220619)
2026-10-16 11:36:32 +01:00
nikstur aba5c2df8e taint: don't taint if /bin, /usr/sbin, /var/run don't exist
It doesn't make sense to taint a system if these fails don't exist.

A missing /usr/sbin for example doesn't indicate an unmerged-bin.
Indeed, if you have no /usr/sbin but only a /usr/bin you have a
perfectly merged bin.

(cherry picked from commit 419cf189d05e0903a233d13db444586cfb2aaf16)
2026-10-16 11:36:32 +01:00
Martin Pitt a9868c9800 vmspawn: actually enable io_uring for disks
vmspawn never used `aio=io_uring` for disks, even when QEMU supports it.
Commit 1a7b6fd9dd added a blockdev probe node named `__io_uring_probe`.
QEMU rejects that name ("Invalid node-name"), as node names have to
start with a letter. The probe then reported io_uring as unsupported.

Use a valid name, following the "vmspawn-" prefix of the other node names.
Check the multi-drive test's debug log for rejected node names to catch
this and similar issues in the future.

Signed-off-by: Martin Pitt <martin@amutable.com>
(cherry picked from commit 9c582182e1ae1e38b7ec2dca29bb279cae83e69b)
2026-10-16 11:36:32 +01:00
Daan De Meyer e7dc2168e7 install: Pass in root prefixed path where needed
The lookup paths are root prefixed in this function, so we need to
pass in the root prefixed path as well to make sure path_is_generator()
does the right thing.

(cherry picked from commit fd6984e2d67fccf54ecf29a3d311e2486423cb98)
2026-10-16 11:36:32 +01:00
Daan De Meyer 3d267223ea systemctl: honour --root= in "is-enabled --full"
We have a root argument, let's make sure we honour it
in this case.

(cherry picked from commit b231b43ff0c3a4b951e45567474052885cad52d3)
2026-10-16 11:36:32 +01:00
Daan De Meyer c74e3aa5b7 install: preset in the scope the caller asked for
unit_file_preset() and unit_file_preset_all() zero-initialized their
install contexts, so their scope was always RUNTIME_SCOPE_SYSTEM. In
the global scope, specifiers in [Install] were then resolved as if for
the system: %U became 0 and a unit got enabled into
target-0.target.wants/. Set the scope the caller asked for, so that
this fails with -EUNATCH instead.

Covered by a new test that presets a unit using %U in the global
scope, with both functions.

(cherry picked from commit 0a4491ef3fce30d31a35c95031c8026a0235e0a2)
2026-10-16 11:36:32 +01:00
Daan De Meyer d14b9ace0c specifier: return -EUNATCH for user and group specifiers in global scope
%u, %U, %g and %G have nothing to resolve to in the global scope, and
failed with -EINVAL. Install code already treats -EUNATCH as "cannot
resolve specifiers": it is listed in ERRNO_IS_NEG_UNIT_ISSUE() and
install_change_dump_error() turns it into a proper message. With
-EINVAL, "systemctl --global enable" of a unit using these specifiers
only reported "Invalid argument".

Return -EUNATCH instead, like the machine-id and os-release
specifiers already do when their source is missing. Only the install
code uses these specifiers in the global scope.

(cherry picked from commit 03ce9bcff23d07751dc6911c7963e3bde9e780c2)
2026-10-16 11:36:32 +01:00
Daan De Meyer cb8fffda7d core: drop the dependency dropin name from the mask log line
The log line reported the file name of the masked dependency symlink, except
that entry is not assigned and is NULL at that point.

(cherry picked from commit 6e6114dd6cafb8d7c9585cf1d4ee58866db42d99)
2026-10-16 11:36:32 +01:00
Kai Lüke 9f00584fc3 test: Cover sysext/confext ordering
The ordering matters at unit startup and when we refresh on updates.
For now, just add a test for the update refresh ordering.

(cherry picked from commit 3bebfc9d85144ffe375ae076a2ba5cf58ade4284)
2026-10-16 11:36:32 +01:00
Kai Lüke efa8139061 sysext: refresh confexts before sysexts on sysupdate notifications
The extension refresh on update did sysext first and then confext but
the units until the previous commit didn't have any ordering. Since it
makes sense to first merge configuration and then the service that might
be influenced by that configuration, this ordering was chosen for the
unit startup path.
Align the update refresh order with the unit startup order.

(cherry picked from commit 2d5e73a485f892059e12d95ef69964bd40d04457)
2026-10-16 11:36:32 +01:00
Kai Lüke 0eee5712fd sysext: Order sysext unit after confext to provide guarantees
Up to now there was no clear ordering of confext and sysext units.
Normally, configuration should be able to influence the behavior of
services (config files or unit drop-ins), so it makes sense to order
confext before sysext. The mounting from the initrd for the final system
makes this less important together with the fact that live merges/
refreshes can encode unit restarts now. Yet I think it's better to know
what gets merged first and if wanted one can avoid encoding restarts if
one doesn't care about later live content changes. Where it matters more
for me is consistent behavior for the refresh check during boot for
non-verity images because they get compared by file handle and mount ID
which means whether the overlay was set up or not determines the
identity and decides if we do a refresh or not and this should not
vary by boot merely due to timing or other dependencies impacting the
ordering. (Note that one extension type shipping another extension type
is not the reason for the ordering and these cycles should be avoided
because they never free the mounts and backing loop devices.)

(cherry picked from commit 7197b862b2a132ea044fed59d914d5eb3e8ae9dd)
2026-10-16 11:36:32 +01:00
WilliButz fdd193ff22 docs: mention LoaderInfo efivar in BLI
(cherry picked from commit cfb11e1feb3c944fb0274c8a326a55b406f09582)
2026-10-16 11:36:32 +01:00
iacopo 5274598b37 man: fix sd_bus_destroy_t return type
(cherry picked from commit 4e7b8f2282430dfb6bac570a908ce47041af8d26)
2026-10-16 11:36:32 +01:00
SecretLUL 29646b6f1c journal-file: don't zero freshly allocated hash tables
The hash tables are only ever set up in newly created journal files, in
space that was just allocated via posix_fallocate() and hence reads as
zeroes anyway, so zeroing the items explicitly is unnecessary.

It is also harmful: the sequential write faults of the memzero() make the
kernel's mmap readahead instantiate the table in ever larger folios, up to
the size of the readahead window, on file systems that support large folios
in the page cache (e.g. XFS, and ext4 since kernel 6.16). And since write
faults on shared file mappings dirty the whole folio, each later update of
a single 16 byte hash bucket then has the whole folio written back. Without
the explicit zeroing, the table's pages are only faulted in when buckets
are first accessed, in random order, and hence mostly as order-0 folios.

Measured on Linux 6.18 with a new journal file (SystemMaxFileSize=50M),
appending 15 syslog-like entries with 23 fields each per second for 120s,
while writing back the file's dirty pages every second, as happens on
machines under page cache pressure, where reclaim keeps waking up the
flusher threads. Bytes written to the (loop) device, median and range of
4-5 runs:

          before                    after
  ext4    182.8M (178.4M-185.7M)    41.2M (31.6M-41.9M)
  xfs     172.7M (161.0M-182.4M)    40.1M (39.7M-44.9M)

This also avoids writing out the whole data hash table once for every new
journal file, i.e. ~2.8% of the maximum file size.

Related: #40262
(cherry picked from commit 6db7cf38d40e8fe6a11392d2f0cc044ed5acf812)
2026-10-16 11:36:32 +01:00
WilliButz 9299c328ac tpm2-util: print log message when search for NvPCR definition fails
Before this change it took some effort to find out why NvPCR related
functions would fail. Specifically, missing NvPCR defintions would let
the `systemd-pcrlogin@` services fail with the following log message:

```
Could not extend NvPCR: No such file or directory
```

There are two annoyances with this: even with log level debug there was
no indication of what is missing, and then there is (at least) one other
reason for the same error to be logged, which is the absence of the PCR
pubkey. The latter can be discovered by setting log level debug for the
affected service.

(cherry picked from commit b43fed88efe34889a49a7710a92141849dc4906d)
2026-10-16 11:36:32 +01:00
Daan De Meyer 26d273d804 nsresourced: Exclude cgroupfs from superblock check
cgroupfs has a single shared global superblock but
programs running in managed user namespaces still
need to be able to write it to make cgroup delegation
work. d381a0d9d5 broke
this by insisting the user namespace owns the
superblock. Let's fix this by excluding cgroupfs from
this check.

(cherry picked from commit 889bc48f101a7cbb56cb4be202e85e1f6d933151)
2026-10-16 11:36:32 +01:00
Zbigniew Jędrzejewski-Szmek 9359eeaf95 NEWS: fix/deduplicate texts about dlopen
The para for libcryptsetup duplicated the text three paras down.

The news for 259 used the phrase "$library support is now implemented via
dlopen()", which is a copy-pasta from an earlier paragraph which talked
about "Linux audit support" and "PAM support". We support PAM, but we
don't "support" libpam, we use it.

(cherry picked from commit 2b24baf2070d01ea8d48651c5052b82dc4c9ece0)
2026-10-16 11:36:32 +01:00
Yu Watanabe 2e8e1bf2d7 test: drop dlopen_gcrypt() test from test-dlopen-so
libgcrypt is used only by test-fsprg. We do not add dlopen notes for
unit tests, so the library may not be installed on the system. If systemd
is built with HAVE_GCRYPT but libgcrypt is not installed, the test fails.

There is no need to install libgcrypt solely for test-dlopen-so, so drop
the test case.

(cherry picked from commit 764b9a724925c4167e91fd36311e38aee8c6871a)
2026-10-16 11:36:32 +01:00
Kamil Monicz f3d4d3e25a socket-proxyd: fix off-by-one in connection limit
The limit is checked before the new connection is added to the set, so
with --connections-max=N and N connections open "set_size() > N" is
false and an additional connection is admitted. Use ">=" to refuse new
connections once the limit is reached.

(cherry picked from commit 9b51efd69fade39b0315251d02d1c9eab929891c)
2026-10-16 11:36:32 +01:00
Kamil Monicz bcf0a9ac58 socket-proxyd: raise RLIMIT_NOFILE at startup
Each proxied connection uses eight file descriptors: the accepted and the
outgoing socket, a duplicate of each, and a pipe for each direction. With
the default soft RLIMIT_NOFILE of 1024, setting up forwarding fails with
"Too many open files" at about 127 concurrent connections, well before
the default --connections-max=256, and the connection is closed right
after being accepted.

socket-proxyd's I/O is sd-event based and handles fds above 1023, so it
does not need the select()-compatible soft limit. Call
rlimit_nofile_bump(-1) at startup to raise RLIMIT_NOFILE as far as
permitted, like udevd does.

(cherry picked from commit 98752540be47778e253cbafe51c7ccdd30f4995e)
2026-10-16 11:36:32 +01:00
Tobias Hunger c74f6f85ed fix(xattr): Handle labels without value
I stumbled over this with the very first image I tried:

> sudo systemd-pull oci --system quay.io/toolbx/arch-toolbox:latest

That failed with a label "user.overlay.origin" with a value of NULL and size 0.

This one-line change allows value == NULL if size == 0 when setting xattrs.

(cherry picked from commit 885fe07ee37cff7316680b5088d11081e01813b1)
2026-10-16 11:36:32 +01:00
Simon de Vlieger d5c945bddb dissect: relate verity partitions
When using `systemd.image_filter=usr=250` a `/usr` was selected based on
its label but the corresponding verity partitions were *not* selected
based on their (potential labels).

This leads to mismatched verity partitions and `dm-verity` failure when
using `image_filter` without also explicitly passing matching
`usr-verity` and `usr-verity-sig`.

Signed-off-by: Simon de Vlieger <cmdr@supakeen.com>
(cherry picked from commit b5326670faac3064bcfa01ae3c1d57565d387bfb)
2026-10-16 11:36:32 +01:00
Fredrik Hugosson b07c5a0639 analyze: Fix leading zero bug in decimals for tool tip in svg plot
Change-Id: If572cc593aa730de87510982613791d94d8f26b5
(cherry picked from commit a446e8ff2c)
2026-10-16 11:36:32 +01:00
Paul Meyer 6d80332e9a test: strip directory from subtest name in summary
The integration tests are started with the absolute path of the test
unit as $0, so run_subtests() derives absolute paths for the subtests
and the summary prints them in full. Show just the script name, the
directory is the same for every entry and only adds noise.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
(cherry picked from commit 0d1ae05a7f)
2026-10-16 11:36:32 +01:00
Robert Beckett ffb5f4bf45 terminal-util: don't query terminal size on virtual consoles
terminal_fix_size() queries the terminal for its dimensions with CSI 18
and DSR. On a virtual console that is pointless: the kernel renders the
screen itself, so TIOCGWINSZ is already authoritative.

It is also slow. PID 1 queries /dev/console from console_setup(), and
writes there go through redirected_tty_write(), so while plymouth holds a
TIOCCONS redirect the query never reaches the VT and no reply is ever
generated. Each query then waits out CONSOLE_ANSI_SEQUENCE_TIMEOUT_USEC.
Previously the write failed immediately with EAGAIN — the kernel forces
O_NONBLOCK on /dev/console — so the query was abandoned at no cost; since
ba10d789a8 it is retried until the timeout instead. On a Steam Deck
booting with console=tty1 and plymouth the two queries cost 667ms, about a
quarter of userspace boot time, and no log level shows it because main()
runs console_setup() between log_close() and log_open().

So skip the query on a virtual console and keep the dimensions the kernel
gave us, reporting success rather than an error: declining to ask is not a
failure, and the "dimensions already match" path below returns 0 for the
same reason.

Note this also skips the query on a /dev/ttyN that would have answered,
and does not help a serial console behind a TIOCCONS redirect.

Fixes: ba10d789a8
Fixes: d91a184509
(cherry picked from commit 4ca7ac0275)
2026-10-16 11:36:32 +01:00
Yu Watanabe 412876f581 test: add missing ASSERT_OK()
Follow-up for 3f4a43f0eb.

Addresses https://github.com/systemd/systemd/pull/43733#discussion_r4087916957

(cherry picked from commit 63850321af)
2026-10-16 11:36:32 +01:00
Michael Vogt 2bd3ff6e81 report: replace METRICS_MAX with a per source limit
The existing limit for the reports was a global METRICS_MAX cap.
However on systems with a verbose socket or with many sockets
that is easily hit and because sockets are contacted in parallel
random parts of the following report generators are skipped.

It seems better to instead make the limit per-source so that one
that is overly verbose cannot starve the others. Because we already
have METRICS_LINKS_MAX this does not add a global limit - we could add
one but it would have the same problem as METRICS_MAX before, some
report would be cut that might be important (or we need to be explicit
about ordering but even then its problematic if we have two
"important" ones and one is buggy and generates too much data).

Note that this keeps the METRICS_PER_SOURCE_MAX at 4096 because
io.systemd.Manager reports a lot, on my idle test VM already
~3k.

We also now report any issue with the metric instead of just the
first one in verb_metrics.

(cherry picked from commit 1cf66d1c67)
2026-10-16 11:36:32 +01:00
Yu Watanabe 97b3c393bf blockdev-list: also ignore ramdisk
This renames BLOCKDEV_LIST_IGNORE_ZRAM to BLOCKDEV_LIST_IGNORE_RAMDISK,
and make it ignores both /dev/ramX and /dev/zramX.

Note, linux-stable by Alpine/postmarketOS has CONFIG_BLK_DEV_RAM=y,
hence the kernel creates /dev/ramX by default. Without this change,
the test case added by 236e7d8a4c fails,
as io.systemd.Repart.ListCandidateDevices varlink method lists the
ramdisks.

(cherry picked from commit 77c51f4e97)
2026-10-16 11:36:32 +01:00
Totoro b0bac1d35b json-stream: preserve message boundaries when receiving file descriptors
An AF_UNIX stream receive can combine a message without file descriptors
with a following SCM_RIGHTS-bearing message. This associates the received
descriptors with the earlier message even when the sender uses separate
sendmsg() calls.

Use the existing boundary-limited read path whenever FD input is enabled
on stream sockets, not only for protocol upgrades. Include the buffered
delimiter suffix in the peek search so a split CRLF delimiter cannot
over-read into the next message either.

Record the input socket type when attaching the descriptors so the new
FD-triggered limit does not truncate packet sockets. Explicit bounded
reads retain their existing semantics.

Add regressions for a oneway request followed by an FD-bearing request,
a continued reply followed by an FD-bearing terminal reply, a split CRLF
delimiter followed by an FD-bearing message, and batched messages on
SOCK_SEQPACKET and SOCK_DGRAM.

Fixes #43823

(cherry picked from commit 3fe57d03a3)
2026-10-16 11:36:32 +01:00
Zbigniew Jędrzejewski-Szmek 25bf98c305 test/fsprg: move includes to appease clang-tidy
Previously in CI:
../src/test/fsprg.c:18:1: error: included header gcrypt-util.h is not used directly [misc-include-cleaner,-warnings-as-errors]
   18 | #include "gcrypt-util.h"
      | ^~~~~~~~~~~~~~~~~~~~~~~~
   19 | #include "memory-util.h"
../src/test/fsprg.c:19:1: error: included header memory-util.h is not used directly [misc-include-cleaner,-warnings-as-errors]
   19 | #include "memory-util.h"
      | ^~~~~~~~~~~~~~~~~~~~~~~~
   20 |
2 warnings treated as errors

(cherry picked from commit 1f286f971e)
2026-10-16 11:36:32 +01:00
Duncan Overbruck 3ee0dcd754 crypto-util: BN_bn2bin asserts have side-effects
(cherry picked from commit 128416f305)
2026-10-16 11:36:32 +01:00
Yu Watanabe ba158ae568 test-ndisc-option: add a round trip test for ndisc options
Co-authored-by: Siteshwar Vashisht <svashisht@redhat.com>
(cherry picked from commit 3f4a43f0eb)
2026-10-16 11:36:32 +01:00
Yu Watanabe 220ab61cd2 ndisc-option: fix parsing/building extended flags
The flags part of the option is 6 bytes. Let's read/write one by one.

Fixes https://github.com/systemd/systemd/pull/43620#discussion_r3913713018.

(cherry picked from commit b628909430)
2026-10-16 11:36:32 +01:00
Yu Watanabe 4bc4705b6b ndisc-option: drop unused argument
(cherry picked from commit 1299c9cc9e)
2026-10-16 11:36:32 +01:00
Siteshwar Vashisht 69b915a059 ndisc: fix an off by 2 write in ndisc_option_build_encrypted_dns()
This function constructs the NDisc Encrypted DNS option (RFC 9463).
`poff` is initialized to `off + sizeof(uint16_t)` - pointing past the 2
bytes SvcParam length field. After all SvcParams are written the length
is set at line 1541. `LESS_BY(poff, off) = poff - off` includes the 2
bytes length field itself. The correct value is `poff - off -
sizeof(uint16_t)`.

(cherry picked from commit d3157f2a67)
2026-10-16 11:36:32 +01:00
Zbigniew Jędrzejewski-Szmek 43cd0e4004 NEWS: typo
(cherry picked from commit 7609c88df2)
2026-10-16 11:36:32 +01:00
Zbigniew Jędrzejewski-Szmek 6176a463f6 hostnamectl: drop space in synopsis
The standard spelling for args that can repeat is without the space.

(cherry picked from commit 244d9bb6c4)
2026-10-16 11:36:32 +01:00
Lennart Poettering 23e31ad577 sysinstall: correct end marker log message
Copypasta...

(cherry picked from commit 0bb2f138f4)
2026-10-16 11:36:32 +01:00
Heran Yang 9a4abe9909 network: find pending address in IPv4 ACD callback
When IPv4 ACD is enabled for a DHCPv4 address, the address remains in
the request queue until ACD succeeds. Hence, when ACD detects a
conflict, the address may not be present in link->addresses yet.

on_acd() currently looks up the address with address_get(), which only
searches link->addresses. This makes the callback return early and
prevents dhcp4_address_on_conflict() from sending DHCPDECLINE.

Use address_get_harder(), which also looks up pending address requests.

Fixes #39460

(cherry picked from commit 2aed6d9ad7)
2026-10-16 11:36:32 +01:00
Yu Watanabe 64f2911bac network: drop pending requests when a DHCP lease is lost or a client is stopped
When a DHCP lease is lost or a client is stopped, there may exist
requests not processed yet. We need to cancel them, otherwise an
address or route requested by the lost lease may be configured later.

(cherry picked from commit 830b60ae1f)
2026-10-16 11:36:32 +01:00
Yu Watanabe ae6dc22b40 network: disable IPv4ACD when the address request is cancelled
If an address with IPv4ACD is requested, then sd_ipv4acd instance for
the address is configured. If the request is cancelled, we should
also disable the IPv4ACD instance.

Note, if the address is already configured, the IPv4ACD instance for the
address will be removed when the address is removed. See address_drop().

(cherry picked from commit c5bf6bac23)
2026-10-16 11:36:32 +01:00
Yu Watanabe 773592d77d network: add a configuration-source filter to link_drop_requests()
Preparation for later changes.

(cherry picked from commit 4be31a9c35)
2026-10-16 11:36:32 +01:00
Alberto Planas 365f24a571 test: check the credentials Varlink error table
credentials_varlink_error_by_errno() answers with the first row whose errno
matches, so two rows sharing one errno make the second unreachable and the
client is told the wrong error. This series re-keys UnexpectedPCRState to
EPERM and adds PCRsKeptChanging on EUCLEAN, so walk the table by id and check
that the errno lookup comes back to the same row, in both errno signs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
(cherry picked from commit 827099139b)
2026-10-16 11:36:32 +01:00
Alberto Planas 9bb8d8de9a tpm2-util: retry NvPCR initialization when PCR values keep changing
tpm2_nvpcr_initialize() already retries the initializing write when
tpm2_extend_nvpcr_nv_index() reports that PCR values changed under its
feet, which the comment there attributes to IMA measurements performed
by the kernel.  The policy session that write needs is opened in the
same loop, and a PCR extended while that policy is submitted makes
tpm2_policy_pcr() return -EUCLEAN, which was propagated as a hard
failure instead.

That is the same transient condition observed one step earlier, so let
the loop absorb it too.

Signed-off-by: Alberto Planas <aplanas@suse.com>
(cherry picked from commit f08bfdbf3d)
2026-10-16 11:36:32 +01:00
Alberto Planas df12508d01 pcrlock: retry policy submission when PCR values keep changing
make_policy() already retries unsealing the recovery PIN when the TPM
reports that PCR values changed, but the tpm2_policy_super_pcr() call
that builds the policy for that unseal attempt was not covered: a
concurrent PCR extension there aborted the whole operation on the first
try.

This is easy to hit when IMA is enabled (e.g. implicitly through secure
boot), as PCR 10 is extended for every kernel module that gets loaded.

Retry that step within the existing loop, and give the retry budget a
name while at it.

Signed-off-by: Alberto Planas <aplanas@suse.com>
(cherry picked from commit 299989fe0b)
2026-10-16 11:36:32 +01:00
Alberto Planas 5f28c87fb6 tpm2-util: log transient PCR changes in tpm2_policy_super_pcr() at debug level
tpm2_policy_pcr() returns -EUCLEAN when the TPM's global PCR update
counter moved while the policy was being submitted, not when the
recorded PCR values disagree with the current state.  Logging "Either
the system has been tampered with or the provided policy is incorrect"
at error level is therefore wrong, and it is noisy too: the condition is
transient and callers are expected to restart the policy session.

Downgrade both occurrences to debug and describe what actually happened,
and document the contract at the declarations.

Signed-off-by: Alberto Planas <aplanas@suse.com>
(cherry picked from commit 1fc5351945)
2026-10-16 11:36:32 +01:00
Alberto Planas 9c420c2f03 creds: don't report a malformed PCR signature file as changing PCRs
tpm2_load_pcr_signature() propagates the JSON parser's errno, and the
parser reports a string that is not valid UTF-8 as -EUCLEAN.  With
EUCLEAN now mapping to io.systemd.Credentials.PCRsKeptChanging, such a
file would be reported as if a PCR were being extended continuously.

Translate it where it originates, so that the errno stays single valued
for every caller of tpm2_load_pcr_signature() and not only for the creds
one: a signature file that cannot be parsed is -EBADMSG, whichever way
it is malformed.  A syntax error used to come out as -EINVAL, which
matched nothing on the way out either.

Signed-off-by: Alberto Planas <aplanas@suse.com>
(cherry picked from commit 2994ca5226)
2026-10-16 11:36:32 +01:00
Alberto Planas a30858ebc3 creds: add io.systemd.Credentials.PCRsKeptChanging error
io.systemd.Credentials.UnexpectedPCRState used to be mapped to EUCLEAN,
which now means "a PCR kept being extended while unsealing" rather than
"the PCR state does not match the policy".  Map it to EPERM instead,
which is one of the errnos ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR() covers,
and introduce a separate PCRsKeptChanging error for EUCLEAN.

Also report the condition explicitly in decrypt_credential_and_warn(),
like the other TPM2 unseal callers do.

Signed-off-by: Alberto Planas <aplanas@suse.com>
(cherry picked from commit 42f3ac664a)
2026-10-16 11:36:32 +01:00
Alberto Planas 1e3fa26b7c cryptsetup,cryptenroll: report continuously changing PCRs explicitly
tpm2_unseal() returns -EUCLEAN specifically when a PCR kept being
extended while unsealing, but the unseal callers no longer catch it
via ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR() and would fall back to the
generic "Failed to unseal secret using TPM2" message.

Give it a message of its own instead, so that the log points at the
actual cause instead of suggesting the system was tampered with.

Signed-off-by: Alberto Planas <aplanas@suse.com>
(cherry picked from commit 941db14b8e)
2026-10-16 11:36:32 +01:00
Alberto Planas c3fdb3ec2e tpm2-util: make -EUCLEAN from tpm2_unseal() mean "PCRs kept changing"
So far tpm2_unseal() used -EUCLEAN together with the errors that
signal that the PCR state does not match the policy.  That is
misleading: -EUCLEAN (and TPM2_RC_PCR_CHANGED) is only ever generated
when the TPM's global PCR update counter moves while we are building the
policy or unsealing, i.e. when something on the system extends a PCR
concurrentlyi (usually IMA extending PCR 10).  It says nothing about
whether the policy itself matches.

Until now the retry loop only recognized those conditions while retries
were left (i > 0), and once the budget was exhausted the last iteration
fell through to the generic paths, reporting either an unrelated policy
error or -ENOTRECOVERABLE.  Handle the last iteration explicitly instead,
and return -EUCLEAN with a message that names the actual problem.

Drop -EUCLEAN from ERRNO_IS_NEG_TPM2_UNSEAL_BAD_PCR(), it is not a "bad
PCR state" error.

Signed-off-by: Alberto Planas <aplanas@suse.com>
(cherry picked from commit 2d54e6b56e)
2026-10-16 11:36:32 +01:00
Yu Watanabe 7898414837 resolve: stop timer event source and detach from browser when a dnssd service is removed
Otherwise, if the timer event source is enabled, a new query may be
invoked by the already removed service.

This also renames dns_remove_service() to dnssd_discovered_service_detach(),
and drops unused DnssdDiscoveredService.query.

(cherry picked from commit 02f65ebead)
2026-10-16 11:36:32 +01:00
Yu Watanabe 3e0080355b resolve: detach DnsServiceBrowser object from Manager when freed or disconnected
When a DnsServiceBrowser object is detached from the manager,
all queries, event sources, and then the reference to Manager should be
dropped. Otherwise, spurious query may be triggered for already
disconnected varlink.

(cherry picked from commit 219abd95ae)
2026-10-16 11:36:32 +01:00
Yu Watanabe 14b91970e6 test-firewall-util: clear test tables in intro() and outro()
Otherwise, the test may fail when there is a garbage in the nftables.

(cherry picked from commit 6f58da1791)
2026-10-16 11:36:32 +01:00
Yu Watanabe 1904ece38b firewall-util: introduce fw_nftables_del_table()
(cherry picked from commit 0ba6d54ef7)
2026-10-16 11:36:31 +01:00
Yu Watanabe a4762e2c79 sd-netlink: add boolean 'add' parameter to sd_nfnl_nft_message_new_table() and friends
Previously, only sd_nfnl_nft_message_new_setelems() takes the 'add'
flag. Let's all functions take the boolean parameter for consistency.

(cherry picked from commit 534a25c885)
2026-10-16 11:36:31 +01:00
Yu Watanabe 33a44fd7a9 sd-netlink: add missing assertions
(cherry picked from commit d47f1599b8)
2026-10-16 11:36:31 +01:00
Yu Watanabe d6e693e460 tar-util: do not fail by adding an unknown acl tag
archive_entry_acl_add_entry() will fail when an unknown tag is set.

(cherry picked from commit 28e7ae95af)
2026-10-16 11:36:31 +01:00
Yu Watanabe efe742d12c tar-util: simplify condition
No functional change, just refactoring.

(cherry picked from commit fa7d15b331)
2026-10-16 11:36:31 +01:00
Yu Watanabe 6bc4bf12f9 tar-util: drop boolean 'skip' flag
No functional change, just refactoring.

(cherry picked from commit fc77a3c1a6)
2026-10-16 11:36:31 +01:00
Yu Watanabe f1a0bfa417 tar-util: use the same table for converting acl tag
Note, ACL_UNDEFINED_TAG == _ARCHIVE_ENTRY_ACL_UNDEFINED, hence this
does not change any behavior.

(cherry picked from commit f19861d9ac)
2026-10-16 11:36:31 +01:00
Birk Skyum bfba34d783 shutdown: preserve console graphics mode across the exitrd handoff
make_console_stdio() forces KD_TEXT while reopening /dev/console. When
systemd-shutdown enters the exitrd, this can expose the text console over
a retained graphical shutdown splash.

Let callers choose whether to switch to text mode, and preserve the mode
for the exitrd handoff. Keep the existing text-mode behavior for manager
reexecution and the crash shell. Restore text mode if executing /shutdown
fails and before reporting a fatal error and freezing.

Add an unsafe, nonparallel virtual-console regression test requiring
explicit opt-in and an already-owned inactive VT in a disposable VM.
Check graphics preservation and text restoration through a private
/dev/console bind mount, retain stderr diagnostics, and restore the saved
mode in the parent even if the child fails.

(cherry picked from commit ef3e0ff7bb)
2026-10-16 11:36:31 +01:00
nikhilnrr 1946818513 test-fstab-generator: fix inverted /mnt symlink guard
The test-18-options.fstab.input scenario was guarded by
"$(readlink /mnt)" != "/mnt", which is true on any normal system
since readlink prints nothing for a plain directory. This meant the
scenario was always skipped, and its fixtures were never actually
compared against generator output.

Fix the guard to check whether /mnt is a symlink directly, and repair
the pre-existing fixtures that had drifted while the scenario was
dead:

  - mnt-wantedby-automount.mount had a stale Where= value and was
    missing the escaping the generator emits for the hyphen in
    /mnt/wantedby-automount.
  - mnt-requires.mount had Requires=/After= in the wrong order.

Also extend the backslash-stripping workaround loop (used because the
.deb packager dislikes files named with a backslash) to cover
.automount units in addition to .mount/.swap, and fix an ordering bug
where -f was checked before -L, which could leave a dangling symlink
when both a unit and its drop-in symlink needed stripping.

(cherry picked from commit 9d27286214)
2026-10-15 17:56:21 +01:00
Chris Coulson a0deef9ce5 report: Don't create TPM2 attestation key with adminWithPolicy
The default attestation key for the TPM2 report signer is currently
created with an empty policy but with the adminWithPolicy attribute set.
This makes it impossible to authorize use of the key for the ADMIN role,
which is required by TPM2_Certify.

This drops the adminWithPolicy attribute so that it can be authorized
using its (empty) authorization value. This is appropriate for local
style attestation keys ("LAKs"). I've been working on an interface for
managing attestation keys which will support creating an IAK, and this
will have both the adminWithPolicy attribute set and a policy defined as
specified in the TCG "TPM 2.0 Keys for Device Identity and Attestation"
spec.

(cherry picked from commit fc5875d137)
2026-10-15 17:56:21 +01:00
Zbigniew Jędrzejewski-Szmek 5a4162e68f docs: fix typo
(cherry picked from commit a415aeb1d2)
2026-10-15 17:39:06 +01:00
Armaan Sandhu f2c17c4f35 strv: measure rebroken lines with utf8_char_console_width() too
strv_rebreak_lines() was the last place left that decoded with the permissive
utf8_encoded_to_unichar() and then asked unichar_console_width() how wide the
result is, so it accepted and measured overlong encodings, surrogates,
noncharacters and the obsolete five and six byte forms that utf8_console_width()
now refuses.

That matters because callers mix the two within a single width computation.
sd-varlink-idl.c sizes its indent with utf8_console_width() and then breaks the
body with strv_rebreak_lines(); verbs.c does the same. One half of the sum
refused a sequence that the other half happily assigned a width to.

Use utf8_char_console_width(), which does the validation and the width in one
step, and advance with utf8_next_char() rather than the decoded length. The
function already refused invalid UTF-8, so the only change is which sequences
count as invalid; it now matches utf8_is_valid(), as everywhere else.

(cherry picked from commit 7cc0257ba8)
2026-10-15 17:39:06 +01:00
Armaan Sandhu dd0699f558 string-util,format-table: measure console width with unichar_console_width()
ellipsize_mem() and align_string_mem() open coded the width of a character as
unichar_iswide(c) ? 2 : 1, but unichar_console_width() counts a tab as eight
cells. The two disagreed, and format-table.c uses both: it decides a field is too
wide with utf8_console_width(), then asks ellipsize() to fit it into that many
columns, and ellipsize() believed a tab was one cell. The ellipsized cell then
still overflowed the column, measured by the very function that had just asked
for it to be truncated. A table pinned to table_set_width(20) emitted lines of
25, 44 and 39 columns. align_string_mem() undercounted the same way and so padded
already overlong cells further.

Use unichar_console_width(), split out for this purpose in 5c0d4b5061. While at
it, let align_string_mem() decode with utf8_char_console_width() as well, so that
the second pass shares both the width model and the validity check with the
measuring pass, instead of keeping a more permissive decoder of its own around
for the next caller to trip over. Its "count invalid chars as 1" fallback now
skips the whole rejected sequence rather than one byte, so that the continuation
bytes are not charged a cell each of their own; the branch should be unreachable
anyway, since our caller only gets there after utf8_console_width() succeeded on
the same string.

Note that unichar_console_width() charges a tab a flat eight cells, while a
terminal advances to the next multiple of eight, so this is deliberately an upper
bound: the two agree only when the tab itself starts on a multiple of eight. A
per character helper cannot do better, because a tab's width is a function of the
column it starts in, and neither ellipsize_mem() nor align_string_mem() is told
what column its string starts at. Overestimating is the safe direction: it can
leave a column padded short, but it cannot overflow one.

ascii_ellipsize_mem() equates bytes with character cells, which holds for ASCII
except for the tab, so keep tabs off that fast path. Like the ANSI sequence case
just above it, such strings now take the generic path, which means they get the
Unicode ellipsis and one reserved cell rather than "..." and three, even in a non
UTF-8 locale.

(cherry picked from commit 0834378fb9)
2026-10-15 17:39:06 +01:00
Armaan Sandhu 5a263ef7ff utf8: make utf8_char_console_width() reject what utf8_is_valid() rejects
utf8_char_console_width() decoded with utf8_encoded_to_unichar(), which does not
check for overlong encodings, does not check unichar_is_valid(), and still
accepts the obsolete five and six byte forms. Those checks live in the wrapper
utf8_encoded_valid_unichar(), which is what utf8_is_valid() and ellipsize_mem()
use. Over all 4244897280 NUL free byte strings of length one to four, that is the
whole UTF-8 encoding space, the wrapper agrees with utf8_is_valid_n() everywhere,
while the bare decoder disagrees on 8835838 of them, always by accepting more.

So utf8_console_width() assigned a finite width to strings that utf8_is_valid()
refuses. format-table.c measures a cell with utf8_console_width() and, if it does
not fit, hands it to ellipsize(), which validates strictly, returns NULL, and is
reported as -ENOMEM. A surrogate, overlong, noncharacter or five byte sequence in
any cell therefore failed the whole table with a bogus out of memory error, and
only once the column happened to be narrow enough to require truncation, so
whether it happened at all depended on the width of the user's terminal. At other
widths the invalid sequence was printed to the terminal instead.

Decode with utf8_encoded_valid_unichar() so that how wide we think a string is
agrees with whether we consider it valid UTF-8 in the first place. Invalid cells
are now refused consistently with -EINVAL, the way the sequences that
utf8_encoded_to_unichar() already rejected always were.

Note that for tables this makes the refusal total rather than per field:
table_data_requested_width_height() turns a SIZE_MAX width into -EINVAL, which
table_format() propagates, so a cell in one of the newly rejected encodings now
fails the whole table at every width. systemd-dissect and repart --dry-run put
GPT partition names read straight off the image into cells without filtering
them, so a crafted partition name suppresses the whole listing where before it
cost one field, and only at some terminal widths. That is the intended trade:
the alternative is to keep emitting raw invalid bytes to the terminal at
whichever widths happen not to need truncation. Should degrading the cell rather
than the table turn out to be preferable, the place for it is where the text
enters the table, via utf8_escape_invalid() and friends, not in a helper whose
job is to say how wide a string is.

This also makes the assert(w >= 0) in utf8_escape_non_printable_full() hold by
construction rather than by the accident that its own validation was stricter
than the width helper's.

(cherry picked from commit cd51add717)
2026-10-15 17:39:05 +01:00
Luca Boccassi 7a086835bb bless-boot: skip gracefully on kexec
If KExecsCount > 0 then do not attempt to mark a UKI, as the stub (and also
any addon and the bootloader) will not have been exercised, so there's no
guaranteed a full reboot with the same image will actually work.

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

(cherry picked from commit 06c2dfa73c)
2026-10-15 17:39:05 +01:00
Georg Müller ed8233ca6f kbd-util: allow kmap as a valid suffix
debian is using kmap suffix in console-data and kbd accepts this too.

(cherry picked from commit 0827be05dd)
2026-10-15 17:39:05 +01:00
Chris Down 14d9e0429e test-journal: Cover journal open and follow edge cases
(cherry picked from commit 532ee29e62)
2026-10-15 17:39:05 +01:00
Chris Down 6031666dbb test-journal: Cover cursor and data lifetime
(cherry picked from commit 8239be1d10)
2026-10-15 17:39:05 +01:00
Chris Down 290bc7714c test-journal: Cover reader position invalidation
(cherry picked from commit 422abe6be6)
2026-10-15 17:39:05 +01:00
Chris Down b104946efc test-journal: Cover duplicate entry storage
(cherry picked from commit 5d49a06cab)
2026-10-15 17:39:05 +01:00
Frantisek Sumsal 8fef1e84b1 dns-packet: limit the number of jumps during packet decompression
So far we didn't limit the number of jumps when decompressing a DNS
packet. This can lead to some extra work with specially crafted packets
that send a staircase of thousands of descending compression pointers,
which can then be amplified by referencing such staircase from thousands
of names.

Given that legitimate DNS packets need only a handful of jumps in the
compression chains, let's limit the number of jumps per a single name to
256 (the same limit as, for example, Unbound currently has).

Reported by opensec-intelligence (OpenSec).

(cherry picked from commit efa16c7f31)
2026-10-15 17:39:05 +01:00
Luca Boccassi e65cb0b583 Create CNAME 2026-09-22 14:41:08 +01:00
Luca Boccassi 78bfec83a3 mkosi: switch debian branch 2026-09-22 15:37:19 +02:00
Luca Boccassi 3cd57753fd semaphore: switch branch 2026-09-22 15:36:16 +02:00
Luca Boccassi 6505b92a7a obs: disable Tumbleweed too
No spec available that can build upstream stable branches
2026-09-22 15:34:26 +02:00
Luca Boccassi d9eb92a3fb obs: switch branch 2026-09-22 15:34:15 +02:00
353 changed files with 6878 additions and 1579 deletions
+1 -1
View File
@@ -67,7 +67,7 @@ jobs:
path: ./out/artifacts path: ./out/artifacts
- name: Upload Sarif - name: Upload Sarif
if: always() && steps.build.outcome == 'success' if: always() && steps.build.outcome == 'success'
uses: github/codeql-action/upload-sarif@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2
with: with:
# Path to SARIF file relative to the root of the repository # Path to SARIF file relative to the root of the repository
sarif_file: cifuzz-sarif/results.sarif sarif_file: cifuzz-sarif/results.sarif
+1 -1
View File
@@ -291,7 +291,7 @@ jobs:
"$HOME/.local/bin/claude" --version "$HOME/.local/bin/claude" --version
- name: Configure AWS credentials - name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c uses: aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd
with: with:
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_ROLE_NAME }} role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_ROLE_NAME }}
role-session-name: GitHubActions-Claude-${{ github.run_id }} role-session-name: GitHubActions-Claude-${{ github.run_id }}
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with: with:
persist-credentials: false persist-credentials: false
- uses: systemd/mkosi@f7762b71437227922a367bb89597843c77494ef9 - uses: systemd/mkosi@71d7b67e01dc47ab5c51f24866c3e2195b9701d2
# Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space # Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space
# immediately, we remove the files in the background. However, we first move them to a different location # immediately, we remove the files in the background. However, we first move them to a different location
@@ -15,7 +15,9 @@ permissions:
jobs: jobs:
lint: lint:
if: github.event.repository.name != 'systemd-security' if: >
github.event.repository.name != 'systemd-security' &&
(github.event_name != 'push' || github.repository == 'systemd/systemd')
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
permissions: permissions:
@@ -29,7 +31,7 @@ jobs:
persist-credentials: false persist-credentials: false
- name: Differential ShellCheck - name: Differential ShellCheck
uses: redhat-plumbers-in-action/differential-shellcheck@d965e66ec0b3b2f821f75c8eff9b12442d9a7d1e uses: redhat-plumbers-in-action/differential-shellcheck@f51c7c0d32777d00de777131d25918617a246415
with: with:
# exclude all `.in` files because they may contain unsupported syntax, and they have to be preprocessed first # exclude all `.in` files because they may contain unsupported syntax, and they have to be preprocessed first
# TEMPORARY: exclude bash completion files, they would generate too many defects in Code scanning dashboard (600+) # TEMPORARY: exclude bash completion files, they would generate too many defects in Code scanning dashboard (600+)
+18 -1
View File
@@ -14,6 +14,23 @@ permissions:
contents: read contents: read
jobs: jobs:
readme-notice:
name: Check for README notice
runs-on: ubuntu-24.04
steps:
- name: Repo checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- name: Check that README.md has no review notice
run: |
if grep -F "Remove this line to confirm you've reviewed this PR before submitting." README.md >/dev/null; then
echo "::error file=README.md,line=1::Remove the review notice from README.md before merging."
exit 1
fi
build: build:
name: Lint Code Base name: Lint Code Base
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
@@ -40,7 +57,7 @@ jobs:
GITHUB_ACTIONS_CONFIG_FILE: actionlint.yml GITHUB_ACTIONS_CONFIG_FILE: actionlint.yml
ENABLE_GITHUB_PULL_REQUEST_SUMMARY_COMMENT: false ENABLE_GITHUB_PULL_REQUEST_SUMMARY_COMMENT: false
- uses: systemd/mkosi@f7762b71437227922a367bb89597843c77494ef9 - uses: systemd/mkosi@71d7b67e01dc47ab5c51f24866c3e2195b9701d2
- name: Check that tabs are not used in Python code - name: Check that tabs are not used in Python code
run: sh -c '! git grep -P "\\t" -- src/core/generate-bpf-delegate-configs.py src/boot/generate-hwids-section.py src/ukify/ukify.py test/integration-tests/integration-test-wrapper.py' run: sh -c '! git grep -P "\\t" -- src/core/generate-bpf-delegate-configs.py src/boot/generate-hwids-section.py src/ukify/ukify.py test/integration-tests/integration-test-wrapper.py'
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
steps: steps:
- name: Release - name: Release
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64
with: with:
prerelease: ${{ contains(github.ref_name, '-rc') }} prerelease: ${{ contains(github.ref_name, '-rc') }}
draft: ${{ github.repository == 'systemd/systemd' }} draft: ${{ github.repository == 'systemd/systemd' }}
+7 -2
View File
@@ -46,6 +46,8 @@ permissions:
jobs: jobs:
ci: ci:
# Don't run on pushes to forks, only on pushes to the upstream repositories
if: github.event_name != 'push' || github.repository == 'systemd/systemd' || github.repository == 'systemd/systemd-stable'
runs-on: ${{ matrix.runner || 'ubuntu-24.04' }} runs-on: ${{ matrix.runner || 'ubuntu-24.04' }}
concurrency: concurrency:
group: ${{ github.workflow }}-${{ matrix.distro }}-${{ matrix.release }}-${{ github.ref }}-${{ matrix.runner || 'ubuntu-24.04' }} group: ${{ github.workflow }}-${{ matrix.distro }}-${{ matrix.release }}-${{ github.ref }}-${{ matrix.runner || 'ubuntu-24.04' }}
@@ -84,7 +86,7 @@ jobs:
release: "9" release: "9"
- distro: centos - distro: centos
release: "10" release: "10"
- distro: postmarketos - distro: nura
release: edge release: edge
libc: musl libc: musl
skip: TEST-92-TPM2-SWTPM skip: TEST-92-TPM2-SWTPM
@@ -93,7 +95,10 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with: with:
persist-credentials: false persist-credentials: false
- uses: systemd/mkosi@f7762b71437227922a367bb89597843c77494ef9 - uses: systemd/mkosi@71d7b67e01dc47ab5c51f24866c3e2195b9701d2
with:
# Bootstrapping a Nura tools tree on the Ubuntu host needs apk
apk: ${{ matrix.distro == 'nura' }}
# Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space # Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space
# immediately, we remove the files in the background. However, we first move them to a different location # immediately, we remove the files in the background. However, we first move them to a different location
+20 -20
View File
@@ -1,23 +1,23 @@
meson==1.11.2 \ meson==1.11.2 \
--hash=sha256:698feae069cef3ecd4d7aaf281d7df359bdfcf555a9a1564383d3b913fa8a736 \ --hash=sha256:698feae069cef3ecd4d7aaf281d7df359bdfcf555a9a1564383d3b913fa8a736 \
--hash=sha256:7e4f6e83fec83e3eaac928e058b073c7557b282c35b6a2024cea143a39926a39 --hash=sha256:7e4f6e83fec83e3eaac928e058b073c7557b282c35b6a2024cea143a39926a39
ninja==1.13.0 \ ninja==1.13.2 \
--hash=sha256:11be2d22027bde06f14c343f01d31446747dbb51e72d00decca2eb99be911e2f \ --hash=sha256:09de9ab04f7352f51570c73fd4913acb1e6c24be0a72cd8b80243d4d3ed04925 \
--hash=sha256:1c97223cdda0417f414bf864cfb73b72d8777e57ebb279c5f6de368de0062988 \ --hash=sha256:0e083700470c02ca154a855ae6d692d03564f5064cae52e113896f9ccc078418 \
--hash=sha256:3c0b40b1f0bba764644385319028650087b4c1b18cdfa6f45cb39a3669b81aa9 \ --hash=sha256:1293f4078278b70d0ee4b6cc8f3a9e030656c9b2f59909970343c4fe76070118 \
--hash=sha256:3d00c692fb717fd511abeb44b8c5d00340c36938c12d6538ba989fe764e79630 \ --hash=sha256:1684c60d031c54c1d049541b64243c0c567dca5463dbd77682a8901780af293d \
--hash=sha256:3d7d7779d12cb20c6d054c61b702139fd23a7a964ec8f2c823f1ab1b084150db \ --hash=sha256:1db9852e528efa7702f5123969f86678663e46d57ff28ab13f5fd84d64a85fb1 \
--hash=sha256:4a40ce995ded54d9dc24f8ea37ff3bf62ad192b547f6c7126e7e25045e76f978 \ --hash=sha256:227cbc3ae3e5e429692388103cae8c09451df086cd2d342dae0795af0d162547 \
--hash=sha256:4be9c1b082d244b1ad7ef41eb8ab088aae8c109a9f3f0b3e56a252d3e00f42c1 \ --hash=sha256:525bfa3fc88aa30a4467df270fd5be6f9fcae8061d54d4df74ea1dc5abd5a975 \
--hash=sha256:5f8e1e8a1a30835eeb51db05cf5a67151ad37542f5a4af2a438e9490915e5b72 \ --hash=sha256:59d71c3e15b6b6f3d903eb0c27285544e0747ca59925ada7037bb1af781ad4b3 \
--hash=sha256:60056592cf495e9a6a4bea3cd178903056ecb0943e4de45a2ea825edb6dc8d3e \ --hash=sha256:65a24341b5ac09fcadcc37082660be40a94174e51a937fabf6e2cae26225fa2c \
--hash=sha256:6739d3352073341ad284246f81339a384eec091d9851a886dfa5b00a6d48b3e2 \ --hash=sha256:6a87bf42b123abe2f37737300185f0a303a891899da85d73a3613ee80547e578 \
--hash=sha256:8cfbb80b4a53456ae8a39f90ae3d7a2129f45ea164f43fadfa15dc38c4aef1c9 \ --hash=sha256:792cadbb9decfd1f776d4d0a6930feb46d08302eb57c176bcf26b09de5748e9f \
--hash=sha256:aa45b4037b313c2f698bc13306239b8b93b4680eb47e287773156ac9e9304714 \ --hash=sha256:81d95081c0ad7c95f67bf682220361ed2a32659d7861b4766b03433c58f22516 \
--hash=sha256:b4f2a072db3c0f944c32793e91532d8948d20d9ab83da9c0c7c15b5768072200 \ --hash=sha256:915bd482c4be41c75120fd67a22e0bb3f0fbb3bbc5f95b89787deadd59e27ef2 \
--hash=sha256:be7f478ff9f96a128b599a964fc60a6a87b9fa332ee1bd44fa243ac88d50291c \ --hash=sha256:919572cbc3f233261ecd41fe1f3efc9d44aa02464a4588867e06a8b4f6f416ea \
--hash=sha256:d741a5e6754e0bda767e3274a0f0deeef4807f1fec6c0d7921a0244018926ae5 \ --hash=sha256:aa3d2ae5706a2c4d1e93edc951d1c6cbb45107413c404f8fde1741239efbc9a0 \
--hash=sha256:e8bad11f8a00b64137e9b315b137d8bb6cbf3086fbdc43bf1f90fd33324d2e96 \ --hash=sha256:b2f687437fac460b27b7eadc99039b1163016fb4ba7276e2782a192d9f24ee0e \
--hash=sha256:fa2a8bfc62e31b08f83127d1613d10821775a0eb334197154c4d6067b7068ff1 \ --hash=sha256:d775a5e43e9088f507a6250d57fcf5678eb31268c545feb5064ffeee33735622 \
--hash=sha256:fb46acf6b93b8dd0322adc3a4945452a4e774b75b91293bafcc7b7f8e6517dfa \ --hash=sha256:f90f84affc441e219f15fe52532806c1c9dbd22fb66c3addddce88a3deaabab7 \
--hash=sha256:fb8ee8719f8af47fed145cced4a85f0755dd55d45b2bddaf7431fa89803c5f3e --hash=sha256:fd82e26c0706ad4ab88e5fdd26f3fab0a987a90f810160f6c322e752c6af298b
+6 -3
View File
@@ -63,7 +63,7 @@ jobs:
run: sudo --preserve-env=GITHUB_ACTIONS,CI,CROSS_ARCH .github/workflows/unit-tests.sh RUN_${{ matrix.run_phase }} run: sudo --preserve-env=GITHUB_ACTIONS,CI,CROSS_ARCH .github/workflows/unit-tests.sh RUN_${{ matrix.run_phase }}
build-musl: build-musl:
name: Build & test (musl, postmarketOS) name: Build & test (musl, Nura)
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
concurrency: concurrency:
group: ${{ github.workflow }}-musl-${{ github.ref }} group: ${{ github.workflow }}-musl-${{ github.ref }}
@@ -74,13 +74,16 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- uses: systemd/mkosi@f7762b71437227922a367bb89597843c77494ef9 - uses: systemd/mkosi@71d7b67e01dc47ab5c51f24866c3e2195b9701d2
with:
# Bootstrapping a Nura tools tree on the Ubuntu host needs apk
apk: true
- name: Build tools tree - name: Build tools tree
run: | run: |
tee mkosi/mkosi.local.conf <<EOF tee mkosi/mkosi.local.conf <<EOF
[Build] [Build]
ToolsTreeDistribution=postmarketos ToolsTreeDistribution=nura
EOF EOF
mkosi -f box -- true mkosi -f box -- true
+10 -4
View File
@@ -1,17 +1,17 @@
rebuild: rebuild:
steps: steps:
- trigger_services: - trigger_services:
project: system:systemd project: system:systemd:stable
package: systemd package: systemd
filters: filters:
event: push event: push
branches: branches:
only: only:
- main - v262-stable
ci: ci:
steps: steps:
- branch_package: - branch_package:
source_project: system:systemd source_project: system:systemd:stable
source_package: systemd source_package: systemd
target_project: system:systemd:ci target_project: system:systemd:ci
# Also prepare some images, but disabled by default to avoid wasting cpu/disk # Also prepare some images, but disabled by default to avoid wasting cpu/disk
@@ -54,6 +54,12 @@ ci:
package: systemd package: systemd
repository: Ubuntu_26.04 repository: Ubuntu_26.04
architecture: i586 architecture: i586
# No packaging support for building SUSE on stable branches
- type: build
status: disable
project: system:systemd:ci
package: systemd
repository: openSUSE_Tumbleweed
# Then enable systemd package builds only, so that images stay disabled # Then enable systemd package builds only, so that images stay disabled
- type: build - type: build
status: enable status: enable
@@ -63,4 +69,4 @@ ci:
event: pull_request event: pull_request
branches: branches:
only: only:
- main - v262-stable
+1 -1
View File
@@ -7,7 +7,7 @@ set -o pipefail
DISTRO="${DISTRO:-debian}" DISTRO="${DISTRO:-debian}"
RELEASE="${RELEASE:-trixie}" RELEASE="${RELEASE:-trixie}"
SALSA_URL="${SALSA_URL:-https://salsa.debian.org/systemd-team/systemd.git}" SALSA_URL="${SALSA_URL:-https://salsa.debian.org/systemd-team/systemd.git}"
BRANCH="${BRANCH:-debian/master}" BRANCH="${BRANCH:-ci/v262-stable}"
ARCH="${ARCH:-amd64}" ARCH="${ARCH:-amd64}"
CONTAINER="${RELEASE}-${ARCH}" CONTAINER="${RELEASE}-${ARCH}"
CACHE_DIR=/var/tmp CACHE_DIR=/var/tmp
+88
View File
@@ -0,0 +1,88 @@
# ANCIENT-MOD: running on old kernels (target: 4.19)
Upstream requires kernel ≥ 5.10 (see `README`, "REQUIREMENTS") and dropped the fallback code for
older kernels. This branch restores or adds fallbacks so the system can at least boot on 4.19.
Code touched by this effort is marked with `ANCIENT-MOD` comments where practical.
Legend: **revert** = reverse-applied an upstream commit (possibly adjusted), **new** = new code
because upstream code was refactored since the fallback was removed.
## Boot-critical
| Area | Kernel feature | Change | Where |
|---|---|---|---|
| Mount point checks (`is_mount_point_at()`, `path_is_mount_point()`), used by early `mount_setup()` for `/proc`, `/sys`, `/dev` with `MNT_FATAL` | `STATX_ATTR_MOUNT_ROOT` (5.8) | **new**: `xstatx_full()` emulates the attribute when it is required but missing: compares the mount id (from `/proc/self/fdinfo`) of the inode with its parent's (`..` for directories, parent path for others); same inode as parent ⇒ root ⇒ mount point. Replaces upstream fallback removed in `a98a6eb95c`. | `src/basic/stat-util.c` (`xstatx_emulate()`) |
| `chase()` (used everywhere), `path_get_mnt_id_at()`, `fds_inode_and_mount_same()`, `XSTATX_MNT_ID_BEST` | `STATX_MNT_ID` (5.8/5.10) | **new**: same emulation fills `stx_mnt_id` from `/proc/self/fdinfo/<fd>` `mnt_id:` (available since 3.15). Replaces removals in `7ecfa87c56`, `e5a3127339`. | `src/basic/stat-util.c` |
| cgroup2 mount | `memory_recursiveprot` (5.7) | **revert** (adjusted) of `80c5b63db5`: option is probed again instead of always passed; if it cannot be probed because `fsopen()` is missing (< 5.2) it is not used. | `src/shared/mount-setup.c` |
| `mount_option_supported()` | `fsopen()` (5.2) | **revert** of part of `c2198d0c3f`: return `-EAGAIN` ("don't know") when the new mount API is unavailable. | `src/basic/mountpoint-util.c` |
| `close_all_fds*()` (every fork/exec, `systemd-executor`) | `close_range()` (5.9) | **revert** of `c471cca093` and `d58c826c54`: fall back to iterating `/proc/self/fd` (or the frugal loop). | `src/basic/fd-util.c`, `src/basic/fd-util.h`, `src/test/test-fd-util.c` |
| `pidref_set_pid()` (every process PID1 tracks, `safe_fork()`, `posix_spawn_wrapper()`) | `pidfd_open()` (5.3) | **revert** (adjusted) of part of `6e14c46bac`: ENOSYS ⇒ PidRef without fd (plain PID). | `src/basic/pidref.c` |
| `pidfd_open()` shim (all pidfd users), `pidfd_waitid()` | `waitid(P_PIDFD)` (5.4) | **new**: vendor kernels (Android 4.19) backport `pidfd_open()` but not `waitid(P_PIDFD)`, so every wait failed with EINVAL (PID1 froze after generators). The shim probes once on a pidfd of self that `pidfd_send_signal()` and `poll()` work (without pidfd poll support a live process reports readable); if not, `pidfd_open()` returns ENOSYS so the plain-PID fallbacks above apply. Waits go through `pidfd_waitid()`, which probes `waitid(P_PIDFD)` (ECHILD = supported, EINVAL = not) and otherwise uses `waitid(P_PID)` with the known PID (safe for children: the PID cannot be reused before reaping). Keeping pidfds is required by logind, which since v258 refuses sessions whose leader has no pidfd (`NoSessionPIDFD`). | `src/libc/pidfd.c`, `src/include/override/sys/pidfd.h`, `src/basic/pidref.c`, `src/libsystemd/sd-event/sd-event.c` |
| `pidref_wait_for_terminate_full()` with timeout | pidfd (5.3) | **new**: without pidfd poll `waitid(P_PID, …, WNOHANG)` every 10 ms instead of returning `-ENOMEDIUM`. | `src/basic/pidref.c` |
| `pidfd_check_pidfs()`, `pidfd_info_mask_is_supported()`, `pidfd_get_inode_id_self_cached()` | pidfd (5.3) | **revert**/new: ENOSYS ⇒ "not supported" instead of hard error. | `src/basic/pidfd-util.c` |
| sd-event child sources (`sd_event_add_child()`, used by udevd, logind, …) | pidfd (5.3), `waitid(P_PIDFD)` (5.4) | **new** (upstream removed the non-pidfd path in `6e14c46bac` and later made the code pidfd-only): if `pidfd_open()` is unsupported the source works on the PID via `waitid(P_PID)` + SIGCHLD signalfd. SIGCHLD is blocked automatically in that case (upstream no longer requires callers to block it). `send_child_signal()` falls back to `kill()`/`rt_sigqueueinfo()`; `set_child_pidfd_own()` returns `-EOPNOTSUPP` without pidfd. | `src/libsystemd/sd-event/sd-event.c` |
| `pam_systemd` session creation | pidfd (5.3) | **revert** of part of `6e14c46bac`: fall back to `CreateSession` (PID based). Ineffective on its own: logind (Varlink and D-Bus) rejects leaders without pidfd, so sessions need a kernel with `pidfd_open()` + pidfd poll. | `src/login/pam_systemd.c` |
| Unit cgroup-empty tracking (`unit_check_cgroup_events()`) | `frozen` key in `cgroup.events` (5.2) | **new**: if the key is missing, read only `populated`. Without this every cgroup event read failed and stopped units were never noticed as empty. | `src/core/cgroup.c` |
| Freeze/thaw | cgroup v2 freezer (5.2) | **revert** of `3c86a935ad`: `cg_freezer_supported()` restored; freeze is `-EOPNOTSUPP` / no-op when `cgroup.freeze` is absent. | `src/basic/cgroup-util.[ch]`, `src/core/cgroup.c`, `src/core/unit.c` |
| Credentials (`LoadCredential=`, `SetCredential=`, `ImportCredential=` — used by many stock units) | new mount API `fsopen`/`fsmount`/`move_mount` (5.2) | **new**: if the credentials fs cannot be created because the API is missing, use the existing "plain directory" fallback (previously only used on EPERM). | `src/core/exec-credential.c` |
| `ProtectProc=` / `ProcSubset=` (used by logind, networkd, timesyncd, hostnamed, …) | per-instance procfs, textual `hidepid=`, `subset=` (5.8) | **new**: on kernels < 5.8 the options are ignored (they would either fail with EINVAL or, worse, change the host's shared `/proc` superblock). `/proc/sys` & friends are then still protected by the normal ProtectKernel* mounts. Upstream removed the old fallback in `0cba5bdcf1`. | `src/core/namespace.c` |
| `RootDirectory=` | `open_tree()` (5.2) | **new**: tolerate ENOSYS when cloning the root directory mount and use the classic bind mount path. | `src/core/namespace.c` |
| `futimens_opath()`, `access_fd()` | `AT_EMPTY_PATH` for `utimensat()`/`faccessat()` (5.8) | **revert** of `52bf232e82` (manually): fall back to `/proc/self/fd/<fd>`. | `src/basic/fs-util.c` |
## Networking
| Area | Kernel feature | Change | Where |
|---|---|---|---|
| `socket_bind_to_ifindex()` (DHCP client, resolved, networkd, …) | `SO_BINDTOIFINDEX` (5.1) | **revert** of `ddbbc98bd5` (manually): fall back to `SO_BINDTODEVICE`. | `src/basic/socket-util.c` |
| `rtnl_resolve_ifname_full()` (alternative names) | `IFLA_ALT_IFNAME` lookup (5.5) | **revert** of `42b09813f4`: treat EINVAL like ENODEV. | `src/libsystemd/sd-netlink/netlink-util.c` |
| networkd startup enumeration | nexthop (5.3) | **revert** of `034b69d8b8` (manually): ignore `-EOPNOTSUPP` from nexthop enumeration, otherwise networkd refuses to start. | `src/network/networkd-manager.c` |
| networkd permanent MAC address | `IFLA_PERM_ADDRESS` (5.6) | **revert** of `04f05d9bd7`: fall back to ethtool. | `src/network/networkd-link.c` |
| IPv6 DNAT (nspawn port forwarding / firewall-util) | nft concatenation fix (5.8) | **revert** of `58fb46ecd5` (manually): `-EOVERFLOW` ⇒ `-EOPNOTSUPP`. | `src/shared/firewall-util.c` |
## Other
| Area | Kernel feature | Change | Where |
|---|---|---|---|
| `SurviveFinalKillSignal=` | `user.*` xattrs on cgroupfs (5.7) | **revert** of `8292b859f3`: fall back to `trusted.survive_final_kill_signal`. | `src/core/cgroup.c`, `src/shared/killall.c` |
| Loop devices via `LOOP_SET_STATUS64` fallback | buffer cache invalidation bug (fixed in 5.0) | **revert** of `5e3887e6c1`: issue `BLKFLSBUF` when offset/size is set. | `src/shared/loop-util.c` |
## Known remaining gaps (not addressed)
- **cgroup v1 is gone upstream**: the kernel must boot with a cgroup v2 hierarchy. 4.19's cgroup v2
lacks the `cpuset` (5.0) and `freezer` (5.2) controllers, `cgroup.kill` (5.14, already graceful).
- **PSI** (4.20): `systemd-oomd` does not work; memory-pressure event sources are already optional.
- **BPF**: features needing BPF links / BPF LSM / bounded loops (5.3–5.7) — `RestrictFileSystems=`,
`RestrictNetworkInterfaces=`, `SocketBind*=`, `BindNetworkInterface=`, … — report "not supported"
(upstream probing, `ef12eadfc8`).
- **New mount API without fallback** (5.2/5.12): `PrivateBPF=`, `ExtensionImages=`/`ExtensionDirectories=`
(overlay via `fsopen`), `MountImages=`, runtime `systemctl bind`/`mount-image`, idmapped mounts,
mountfsd, nsresourced, sysext/confext, homed (also needs fscrypt v2 / 5.4), coredump's mount of
the crashed process' root.
- **`MS_NOSYMFOLLOW`** (5.10) is passed as a legacy `mount(2)` flag; older kernels silently ignore
unknown flags, so the mount just lacks `nosymfollow`.
- **Credentials** use a plain directory instead of a dedicated (noswap) tmpfs, i.e. less isolation.
- **Per-device IO weight** (`IODeviceWeight=`, BFQ per-device weight, 5.4): upstream dropped the
EINVAL workaround (`00c4851af0`), expect warnings when used.
- **udev net_id** for IP-over-InfiniBand (`dev_port`, 4.20): `d3d375a686` not reverted; multi-port
IPoIB devices may get colliding names.
- `test-event`'s `test_pidfd` inherently requires pidfds and fails without them; it and
`test_child_pidfd_wnowait` also call `waitid(P_PIDFD)` directly and fail without it.
- logind sessions require pidfds (see `pam_systemd` row); on kernels without `pidfd_open()` no
login session can be created.
- Anything else newer than 5.10 listed in `README` as "recommended baseline" is expected to fall
back gracefully upstream, but that has not been verified on a real old kernel.
## Testing done
- Full native test suite (`meson test -C build`) on a 7.x kernel.
- Selected tests (`test-stat-util`, `test-mountpoint-util`, `test-chase`, `test-fs-util`,
`test-fd-util`, `test-pidref`, `test-process-util`, `test-socket-util`, `test-mount-util`,
`test-udev-spawn`, `test-async`, `test-event` except `test_pidfd`) and `systemd --test --system`
(with the built generators) under an `LD_PRELOAD` shim that simulates an old kernel: strips
`STATX_MNT_ID*`/`STATX_ATTR_MOUNT_ROOT` from `statx()` results and makes `pidfd_open`,
`pidfd_send_signal`, `pidfd_spawn`, `close_range` and the new mount API return ENOSYS.
- `test-pidref`, `test-process-util`, `test-event` (except `test_pidfd`, `test_child_pidfd_wnowait`)
under an `LD_PRELOAD` shim that only makes `waitid(P_PIDFD)` fail with EINVAL (Android 4.19
vendor kernel case: pidfds stay enabled, waits use the `P_PID` fallback).
- Booted on an Android 4.19 vendor kernel (Xiaomi vince): reaches `graphical.target`; login
sessions not verified yet.
+9 -17
View File
@@ -681,7 +681,7 @@ CHANGES WITH 262:
inspired by unit file's ConditionXYZ= settings, and allows marking inspired by unit file's ConditionXYZ= settings, and allows marking
components and features as suggested for installation under various components and features as suggested for installation under various
conditions (such as architecture, used virtualization, host identity, conditions (such as architecture, used virtualization, host identity,
kernel command line, version, firmware properties and machine tag). kernel command line, version, firmware properties and machine tags).
All components currently suggested can be enabled via All components currently suggested can be enabled via
'systemd-sysupdate enable-component --component-suggested' (and 'systemd-sysupdate enable-component --component-suggested' (and
similarly for features). Note that by providing hwdb files that match similarly for features). Note that by providing hwdb files that match
@@ -1464,10 +1464,6 @@ CHANGES WITH 261:
booting on UEFI firmware that supports TPMs, avoiding spurious booting on UEFI firmware that supports TPMs, avoiding spurious
errors on systems without a TPM. errors on systems without a TPM.
* libcryptsetup is now loaded via dlopen() in the cryptsetup
binaries, eliminating the hard runtime dependency for systems that do
not actually use it.
* systemd-cryptenroll now defaults to sealing the LUKS2 key using * systemd-cryptenroll now defaults to sealing the LUKS2 key using
RSA-OAEP with SHA-256 (or SHA-1 if the hardware doesn't support it), RSA-OAEP with SHA-256 (or SHA-1 if the hardware doesn't support it),
in order to make the setup more robust against theoretical future in order to make the setup more robust against theoretical future
@@ -1476,7 +1472,7 @@ CHANGES WITH 261:
Changes in Dynamic Linking: Changes in Dynamic Linking:
* libgnutls, libmicrohttpd, libcurl, libcrypto, libssl, libfdisk * libgnutls, libmicrohttpd, libcurl, libcrypto, libssl, libfdisk,
and libcryptsetup are now consistently loaded via dlopen() and libcryptsetup are now consistently loaded via dlopen()
throughout the codebase, further reducing the set of mandatory throughout the codebase, further reducing the set of mandatory
dependencies from all binaries. dependencies from all binaries.
@@ -2531,19 +2527,15 @@ CHANGES WITH 259:
the PAM modules pam_systemd + pam_systemd_home + pam_systemd_loadkey, the PAM modules pam_systemd + pam_systemd_home + pam_systemd_loadkey,
which are loaded by PAM and hence need PAM anyway to operate). which are loaded by PAM and hence need PAM anyway to operate).
* Similarly, libacl support is now implemented via dlopen(). * Similarly, libmount is now loaded via dlopen().
* Similarly, libblkid support is now implemented via dlopen(). Note: libmount still must be installed for systemd to manage the
system. However, libsystemd.so no longer requires it, and neither do
various ways to invoke the systemd service manager binary other than
to manage the system.
* Similarly, libseccomp support is now implemented via dlopen(). * Similarly, libacl, libblkid, libseccomp, libselinux are loaded via
dlopen().
* Similarly, libselinux support is now implemented via dlopen().
* Similarly, libmount support is now implemented via dlopen(). Note,
that libmount still must be installed in order to invoke the service
manager itself. However, libsystemd.so no longer requires it, and
neither do various ways to invoke the systemd service manager binary
short of using it to manage a system.
* systemd no longer links against libcap at all. The simple system call * systemd no longer links against libcap at all. The simple system call
wrappers and other APIs it provides have been reimplemented directly wrappers and other APIs it provides have been reimplemented directly
+1 -1
View File
@@ -68,7 +68,7 @@ REQUIREMENTS:
still function, but upstream support and testing are limited. still function, but upstream support and testing are limited.
Linux kernel ≥ 5.15 for MPOL_PREFERRED_MANY NUMA policy Linux kernel ≥ 5.15 for MPOL_PREFERRED_MANY NUMA policy
≥ 6.3 for MFD_EXEC/MFD_NOEXEC_SEAL and tmpfs noswap option ≥ 6.3 for MFD_EXEC/MFD_NOEXEC_SEAL, F_SEAL_EXEC, and tmpfs noswap option
≥ 6.5 for name_to_handle_at() AT_HANDLE_FID, SO_PEERPIDFD/SO_PASSPIDFD, ≥ 6.5 for name_to_handle_at() AT_HANDLE_FID, SO_PEERPIDFD/SO_PASSPIDFD,
and MOVE_MOUNT_BENEATH and MOVE_MOUNT_BENEATH
≥ 6.6 for quota support on tmpfs ≥ 6.6 for quota support on tmpfs
+26
View File
@@ -1040,6 +1040,32 @@ The Trusted Platform Module's (TPM) NV index support is too limited to properly
implement NV index backed additional PCRs. NvPCRs will not be allocated or implement NV index backed additional PCRs. NvPCRs will not be allocated or
initialized, and will not be available on the system. initialized, and will not be available on the system.
-- 7a427613a56946b6bfa9aee1dfc553cd
Subject: Initialization of NvPCR not authorized in this boot
Defined-By: systemd
Support: %SUPPORT_URL%
Documentation: man:systemd-measure(1) man:ukify(1) man:systemd-tpm2-setup.service(8)
An additional NV index backed Platform Configuration Register (PCR) could not be
initialized, because the authorization required for its initializing write is
not available. The initializing write to an NvPCR must be authorized by a signed
PCR policy with the "initrd" policy reference, which is only possible from the
initrd. This happens if the booted unified kernel image (UKI) does not carry a
PCR public key (in its .pcrpkey section), if it does not carry a signed PCR
policy (in its .pcrsig section) for that key with the "initrd" policy
reference, or if initialization was attempted after the system transitioned
from the initrd to the host, for example because
systemd-tpm2-setup-early.service is not included in the initrd.
This is not an error: the affected NvPCRs will not be available during this
boot, and measurements to them will be skipped.
To make NvPCRs available, sign the UKI's PCR policy for the initrd boot phase
with the "initrd" policy reference, for example via the --policyref=initrd and
--phase=enter-initrd options of systemd-measure, or the corresponding options
of ukify, and make sure systemd-tpm2-setup-early.service is included in the
initrd.
-- eac6d394c925493deac2ba99f3c2bb11 -- eac6d394c925493deac2ba99f3c2bb11
Subject: An optional dependency for @FEATURE@ is not installed Subject: An optional dependency for @FEATURE@ is not installed
Defined-By: systemd Defined-By: systemd
+4
View File
@@ -197,6 +197,10 @@ Variables will be listed below using the Linux efivarfs naming,
first sets the variable, and its presence suppresses a second measurement of first sets the variable, and its presence suppresses a second measurement of
the same data into the same PCR during the same boot. the same data into the same PCR during the same boot.
* The EFI variable `LoaderInfo-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f`
contains the version string of the boot loader that was booted,
e.g. `systemd-boot 262`. It is formatted as a NUL-terminated UTF-16 string.
If `LoaderTimeInitUSec` and `LoaderTimeExecUSec` are set, `systemd-analyze` If `LoaderTimeInitUSec` and `LoaderTimeExecUSec` are set, `systemd-analyze`
will include them in its boot-time analysis. If `LoaderDevicePartUUID` is set, will include them in its boot-time analysis. If `LoaderDevicePartUUID` is set,
systemd will mount the ESP that was used for the boot to `/boot`, but only if systemd will mount the ESP that was used for the boot to `/boot`, but only if
+1
View File
@@ -0,0 +1 @@
systemd.io
+1 -1
View File
@@ -26,7 +26,7 @@ That means explicitly, that:
1. The root control group may only be written to by systemd (PID 1). Services that create and manipulate control groups in the top level cgroup are in direct conflict with the kernel's requirement that each control group should have a single-writer only. 1. The root control group may only be written to by systemd (PID 1). Services that create and manipulate control groups in the top level cgroup are in direct conflict with the kernel's requirement that each control group should have a single-writer only.
2. Services must set Delegate=yes for the units they intend to manage subcgroups of. If they create and manipulate cgroups outside of units that have Delegate=yes set, they violate the access contract for control groups. 2. Services must set Delegate=yes for the units they intend to manage subcgroups of. If they create and manipulate cgroups outside of units that have Delegate=yes set, they violate the access contract for control groups.
For a more high-level background story, please have a look at this [Linux Foundation News Story](https://www.linuxfoundation.jp/blog/2013/08/all-about-the-linux-kernel-cgroups-redesign/). For a more high-level background story, please have a look at this [Linux.com News Story](https://www.linux.com/news/all-about-linux-kernel-cgroups-redesign/).
### Why this all again? ### Why this all again?
+3 -1
View File
@@ -402,7 +402,9 @@ All tools:
* `$SYSTEMD_LOCALE_DIRECTORY=` — The directory must be absolute and normalized. * `$SYSTEMD_LOCALE_DIRECTORY=` — The directory must be absolute and normalized.
If unset, the default locale directory of the C library (`/usr/lib/locale/` If unset, the default locale directory of the C library (`/usr/lib/locale/`
for glibc and `/usr/share/i18n/locales/musl/` for musl) will be used. for glibc) will be used. On musl, directories `/etc/musl/locale`,
`/usr/share/musl/locale`, `/share/musl/locale` and for compatibility reasons
`/usr/share/i18n/locales/musl` will be searched.
`systemd-resolved`: `systemd-resolved`:
+1 -2
View File
@@ -41,8 +41,7 @@ Specifically, the following concepts are available:
invalidating all prior keys associated with the security chip and generating invalidating all prior keys associated with the security chip and generating
a new seed key. a new seed key.
* The * The `systemd-factory-reset-reboot.service`
[`systemd-factory-reset-reboot.service`](https://www.freedesktop.org/software/systemd/man/latest/systemd-factory-reset-reboot.service.html)
unit automatically reboots the system as part of `factory-reset.target`. It unit automatically reboots the system as part of `factory-reset.target`. It
is ordered after `systemd-tpm2-clear.service` and is ordered after `systemd-tpm2-clear.service` and
`systemd-factory-reset-request.service` in order to initiate the reboot that `systemd-factory-reset-request.service` in order to initiate the reboot that
+1 -1
View File
@@ -9,7 +9,7 @@ SPDX-License-Identifier: LGPL-2.1-or-later
_So you are working on a Linux distribution or appliance and need very fast boot-ups?_ _So you are working on a Linux distribution or appliance and need very fast boot-ups?_
systemd can already offer boot times of < 1s for the Core OS (userspace only, i.e. only the bits controlled by systemd) and < 2s for a complete up-to-date desktop environments on simpler (but modern, i.e. SSDs) laptops if configured properly (examples: [http://git.fenrus.org/tmp/bootchart-20120512-1036.svg](http://git.fenrus.org/tmp/bootchart-20120512-1036.svg)). systemd can already offer boot times of < 1s for the Core OS (userspace only, i.e. only the bits controlled by systemd) and < 2s for a complete up-to-date desktop environments on simpler (but modern, i.e. SSDs) laptops if configured properly.
In this page we want to suggest a couple of ideas how to achieve that, and if the resulting boot times do not suffice where we believe room for improvements are that we'd like to see implemented sooner or later. In this page we want to suggest a couple of ideas how to achieve that, and if the resulting boot times do not suffice where we believe room for improvements are that we'd like to see implemented sooner or later.
+60
View File
@@ -0,0 +1,60 @@
---
title: TPM NV Index Assignments by systemd
category: Booting
layout: default
SPDX-License-Identifier: LGPL-2.1-or-later
---
# TPM NV Index Assignments by systemd
The Trusted Computing Group (TCG) maintains a [Registry of Reserved TPM 2.0
Handles and Localities](https://trustedcomputinggroup.org/resource/registry/)
which assigns TPM 2.0 NV index ranges (among other things, see section 2.2) to
organizations (by convention only!). It has assigned the NV index range
**0x01D10200-0x01D105FF** to the Linux community. Subranges of this range are
delegated to individual projects by the [UAPI.19 Linux TPM NV Index
Registry](https://uapi-group.org/specifications/specs/linux_tpm_nvindex_registry/),
which delegated the NV index range **0x01D10200-0x01D10224** (i.e. 37 NV
indexes) to the systemd project. systemd uses this range as follows:
| NV Index | Number | Use |
|-----------------------|--------|---------------------------------------------------------------------------------------|
| 0x01D10200 | 1 | NvPCR `hardware`: SMBIOS product UUID of the system |
| 0x01D10201 | 1 | NvPCR `cryptsetup`: LUKS volume unlock mechanism used (TPM2, PKCS#11, FIDO2, …) |
| 0x01D10202 | 1 | NvPCR `verity`: Signed Verity images activated (e.g. system/configuration extensions) |
| 0x01D10203 | 1 | NvPCR `login`: User records of users logging in |
| 0x01D10204-0x01D1020C | 9 | Currently unused |
| 0x01D1020D-0x01D10224 | 24 | `systemd-pcrlock` `PolicyAuthorizeNV` policy hashes |
Each of the NvPCR indexes stores a single SHA256 hash, and is hence
expected to be 32 bytes in size. The `systemd-pcrlock` policy hashes
are stored as `TPMT_HA` structures, i.e. the hash is prefixed by the
16-bit hash algorithm identifier, hence these NV indexes are 34 bytes
in size.
NvPCRs are additional PCRs implemented in NV indexes of type `TPM2_NT_EXTEND`,
see [TPM2 PCR Measurements](/TPM2_PCR_MEASUREMENTS) for details. They are
statically assigned and shared between all Linux/systemd based OSes installed
on the same system. Their base NV index may be changed at build time via the
`-Dtpm2-nvpcr-base=` meson option, the table above lists the default
assignments.
The `systemd-pcrlock` policy hashes are allocated dynamically at OS
installation time, one for each installed OS that uses `systemd-pcrlock`-based
disk encryption policies. An NV index is picked randomly from the subrange
(retrying on collision), hence at most 24 such OSes can be installed on the same
system.
The unused range might be allocated later, for any purpose. Note that the NV
index immediately following the range delegated to systemd is assigned to a
different purpose by UAPI.19. Should systemd require additional NV indexes in
the future, a separate subrange has to be requested from UAPI.19.
## Relationship with UAPI.19
This document is referenced by the [UAPI.19 Linux TPM NV Index
Registry](https://uapi-group.org/specifications/specs/linux_tpm_nvindex_registry/)
for details about assignments of the NV index range delegated to the systemd
project. Hence, particular care should be taken that this page is not moved, and
its URL remains stable as
[`https://systemd.io/TPM2_NVINDEX_ASSIGNMENTS`](https://systemd.io/TPM2_NVINDEX_ASSIGNMENTS).
+4 -3
View File
@@ -53,9 +53,10 @@ the NV index handle space.
The NV index range to use for this is configurable at build time, so that The NV index range to use for this is configurable at build time, so that
downstreams have some flexibility to change this if they want. This uses the downstreams have some flexibility to change this if they want. This uses the
0x01d10200 NV index as base by default. To abstract the actual nvindex number 0x01d10200 NV index as base by default (see [TPM NV Index Assignments by
away there's a naming concept, so that nvindexes are referenced by name string systemd](/TPM2_NVINDEX_ASSIGNMENTS) for the NV index ranges systemd uses). To
rather than number. abstract the actual nvindex number away there's a naming concept, so that
nvindexes are referenced by name string rather than number.
NvPCRs are defined in little JSON snippets in `/usr/lib/nvpcr/*.nvpcr`, that NvPCRs are defined in little JSON snippets in `/usr/lib/nvpcr/*.nvpcr`, that
match up index number and name, as well as pick a hash algorithm. The recognized match up index number and name, as well as pick a hash algorithm. The recognized
+12 -4
View File
@@ -33,10 +33,10 @@ SPDX-License-Identifier: LGPL-2.1-or-later
data that other functions can later consume to create a similar object. data that other functions can later consume to create a similar object.
Example: `io.systemd.Unit.List` outputs unit configuration, which can later Example: `io.systemd.Unit.List` outputs unit configuration, which can later
be reused to create another unit via `io.systemd.Unit.StartTransient` (not be reused to create another unit via `io.systemd.Unit.StartTransient`.
implemented yet). The `io.systemd.Unit.StartTransient` call should accept The `io.systemd.Unit.StartTransient` call should accept only the 'context'
only the 'context' portion of the output, without requiring any runtime data portion of the output, without requiring any runtime data such as state
such as state (e.g. pid) or statistics. (e.g. pid) or statistics.
- Following the guideline above, any field within 'context' should be nullable - Following the guideline above, any field within 'context' should be nullable
by default. This ensures that when a context structure is used as input, the by default. This ensures that when a context structure is used as input, the
@@ -46,6 +46,14 @@ SPDX-License-Identifier: LGPL-2.1-or-later
Fields that cannot logically be omitted in input (e.g. a unit type) may remain Fields that cannot logically be omitted in input (e.g. a unit type) may remain
non-nullable. non-nullable.
- Input may accept multiple representations of the same information. Output
should be normalized and must not include the same information in multiple
forms. Every output field in a reusable context must be accepted on input,
so that the context can be fed back without conversion or removal of fields.
For example, the context returned by `io.systemd.Unit.List` must be usable
as input to `io.systemd.Unit.StartTransient`. The same principle applies to
other interfaces that share structures between output and input.
# Enums # Enums
- Enum fields in the codebase must be exposed as string values in Varlink, not - Enum fields in the codebase must be exposed as string values in Varlink, not
+1 -1
View File
@@ -31,7 +31,7 @@ Minimal porting (without multi-seat) requires the following:
3. Make sure to register your logged in session via the PAM session stack as well, also including pam_systemd in it. 3. Make sure to register your logged in session via the PAM session stack as well, also including pam_systemd in it.
4. Optionally, use pam_misc_setenv() to set the environment variables XDG_SEAT and XDG_VTNR. 4. Optionally, use pam_misc_setenv() to set the environment variables XDG_SEAT and XDG_VTNR.
The former should contain "seat0", the latter the VT number your session runs on. pam_systemd can determine these values automatically but it's nice to pass these variables anyway. The former should contain "seat0", the latter the VT number your session runs on. pam_systemd can determine these values automatically but it's nice to pass these variables anyway.
In summary: porting a display manager from ConsoleKit to systemd primarily means removing code, not necessarily adding any new code. Here, a cheers to simplicity! In summary: porting a display manager from ConsoleKit to systemd primarily means removing code, not necessarily adding any new code. Hear, cheers to simplicity!
1. Subscribe to seats showing up and going away, via the systemd-logind D-Bus interface's SeatAdded and SeatRemoved signals. 1. Subscribe to seats showing up and going away, via the systemd-logind D-Bus interface's SeatAdded and SeatRemoved signals.
Take possession of each seat by spawning your greeter on it. Take possession of each seat by spawning your greeter on it.
+8
View File
@@ -72,6 +72,14 @@ dmi:bvnLENOVO*
dmi:bvnMicrosoft Corporation*:pvrSurface with Windows 8 Pro* dmi:bvnMicrosoft Corporation*:pvrSurface with Windows 8 Pro*
ID_CHASSIS=tablet ID_CHASSIS=tablet
# Microsoft Surface Go 3 is a detachable, but reports chassis type 9 (Laptop)
dmi:*:svnMicrosoftCorporation:pnSurfaceGo3:*
ID_CHASSIS=convertible
# GPD Pocket 4 chassis type # GPD Pocket 4 chassis type
dmi:bvnAmericanMegatrendsInternational*:rvnGPD:rnG1628-04* dmi:bvnAmericanMegatrendsInternational*:rvnGPD:rnG1628-04*
ID_CHASSIS=convertible ID_CHASSIS=convertible
# Google Pixelbook (Eve) is a convertible, but reports chassis type 3 (Desktop)
dmi:*:svnGoogle:pnEve:*
ID_CHASSIS=convertible
+9
View File
@@ -1023,6 +1023,15 @@ evdev:input:b0003v2179p0004*
EVDEV_ABS_00=::234 EVDEV_ABS_00=::234
EVDEV_ABS_01=::328 EVDEV_ABS_01=::328
#########################################
# VEIKK
#########################################
# VEIKK A15 Pro
evdev:input:b0003v2FEBp0006*
EVDEV_ABS_00=::129
EVDEV_ABS_01=::215
######################################### #########################################
# Waltop # Waltop
######################################### #########################################
+10
View File
@@ -139,3 +139,13 @@ id-input:modalias:input:b0003v06A3p0763*
# PXN HB S handbrake # PXN HB S handbrake
id-input:modalias:input:b0003v11FFpA701* id-input:modalias:input:b0003v11FFpA701*
ID_INPUT_JOYSTICK=1 ID_INPUT_JOYSTICK=1
# Retoo E803 Air Mouse
id-input:usb:v1915p1025:name:*Consumer Control*:*
ID_INPUT_TABLET=0
ID_INPUT_TABLET_PAD=0
# Samsung Galaxy Book2 Go internal keyboard
id-input:modalias:input:b0018v0CF2p9028e0100-e0,1,2,3,4*
ID_INPUT_TABLET=
ID_INPUT_TABLET_PAD=
+29
View File
@@ -345,6 +345,15 @@ evdev:name:AT Translated Set 2 keyboard:dmi:*:svnAYANEO:*
evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*BenQ*:pn*Joybook*R22*:* evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*BenQ*:pn*Joybook*R22*:*
KEYBOARD_KEY_6e=wlan KEYBOARD_KEY_6e=wlan
###########################################################
# Casper
###########################################################
evdev:atkbd:dmi:bvn*:bvr*:bd*:svn*CASPER*:pn*NIRVANA*:*
KEYBOARD_KEY_a0=!mute
KEYBOARD_KEY_ae=!volumedown
KEYBOARD_KEY_b0=!volumeup
########################################################### ###########################################################
# Clevo # Clevo
########################################################### ###########################################################
@@ -639,6 +648,21 @@ evdev:input:b0003v18D1p8001*
evdev:input:b0003v18D1p8007* evdev:input:b0003v18D1p8007*
KEYBOARD_KEY_b002f=reserved # Disable micmute key KEYBOARD_KEY_b002f=reserved # Disable micmute key
# Google Pixelbook (Eve)
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnGoogle:pnEve:*
KEYBOARD_KEY_3b=back # F1 Back
KEYBOARD_KEY_3c=refresh # F2 Refresh
KEYBOARD_KEY_3d=zoom # F3 Fullscreen
KEYBOARD_KEY_3e=scale # F4 Overview
KEYBOARD_KEY_3f=brightnessdown # F5 Brightness down
KEYBOARD_KEY_40=brightnessup # F6 Brightness up
KEYBOARD_KEY_41=playpause # F7 Play/Pause
KEYBOARD_KEY_42=mute # F8 Mute
KEYBOARD_KEY_43=volumedown # F9 Volume down
KEYBOARD_KEY_44=volumeup # F10 Volume up
KEYBOARD_KEY_5d=controlpanel # Menu key
KEYBOARD_KEY_d8=assistant # Assistant key
########################################################### ###########################################################
# Haier # Haier
########################################################### ###########################################################
@@ -1176,6 +1200,11 @@ evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO:pn21N5*:pvrThinkBook16pG5IRX:*
evdev:name:Ideapad extra buttons:dmi:*:svnLENOVO:pn21MV:pvrThinkBook14G7ARP:* evdev:name:Ideapad extra buttons:dmi:*:svnLENOVO:pn21MV:pvrThinkBook14G7ARP:*
KEYBOARD_KEY_13e=unknown # Fn+F4 mic mute, also emitted as scan code 0x8, ignore KEYBOARD_KEY_13e=unknown # Fn+F4 mic mute, also emitted as scan code 0x8, ignore
# Lenovo ThinkBook 16 G7 ARP (Type 21MW)
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLENOVO*:pn21MW*:pvr*
KEYBOARD_KEY_ae=!volumedown
KEYBOARD_KEY_b0=!volumeup
evdev:atkbd:dmi:*:svnLENOVO:*:pvrLenovoYoga300-11IBR:* evdev:atkbd:dmi:*:svnLENOVO:*:pvrLenovoYoga300-11IBR:*
KEYBOARD_KEY_62=unknown # Touchpad on, also emitted by "Ideapad extra buttons", ignore KEYBOARD_KEY_62=unknown # Touchpad on, also emitted by "Ideapad extra buttons", ignore
KEYBOARD_KEY_63=unknown # Touchpad off, also emitted by "Ideapad extra buttons", ignore KEYBOARD_KEY_63=unknown # Touchpad off, also emitted by "Ideapad extra buttons", ignore
+7
View File
@@ -794,6 +794,13 @@ sensor:modalias:acpi:KIOX000A:*:dmi:*:rvnMETAPHYUNI:rnMetawillBook01:* # Meta
sensor:modalias:acpi:KIOX000A:*:dmi:*:svnMicrotech:pne-tabPro:* # Microtech e-tab Pro sensor:modalias:acpi:KIOX000A:*:dmi:*:svnMicrotech:pne-tabPro:* # Microtech e-tab Pro
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1 ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
#########################################
# Minisforum
#########################################
sensor:modalias:acpi:SMOCF05:*:dmi:*:svnMicroComputer(HK)TechLimited:pnV3*:* # V3, V3 SE
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, 1
######################################### #########################################
# MPMAN # MPMAN
######################################### #########################################
+15
View File
@@ -253,6 +253,21 @@ usb:v17CCp1130*
usb:v17CCp2420* usb:v17CCp2420*
ID_AV_PRODUCTION_CONTROLLER=1 ID_AV_PRODUCTION_CONTROLLER=1
####################
# PCPanel
####################
# PCPanel Mini
usb:v0483pA3C4*
ID_AV_PRODUCTION_CONTROLLER=1
# PCPanel Pro
usb:v0483pA3C5*
ID_AV_PRODUCTION_CONTROLLER=1
# PCPanel RGB
usb:v04D8pEB52*
ID_AV_PRODUCTION_CONTROLLER=1
#################### ####################
# Pioneer # Pioneer
#################### ####################
+14 -7
View File
@@ -8,16 +8,23 @@
<refsect1> <refsect1>
<title/> <title/>
<!-- for individual section(s) of a manpage --> <!-- for individual sections of a manpage -->
<para id="singular">This option is experimental and subject to change at any given moment without notice. <para id="option">This option is experimental and subject to change without advance notice.
It will be stabilized and given a backward-compatibility guarantee in a future release.</para> It will be stabilized and given a backward-compatibility guarantee in a future release,
but may also possibly be removed.</para>
<para id="plural">These options are experimental and subject to change at any given moment without notice. <para id="options">These options are experimental and subject to change without advance notice.
They will be stabilized and given a backward-compatibility guarantee in a future release.</para> They will be stabilized and given a backward-compatibility guarantee in a future release,
but may also possibly be removed.</para>
<para id="feature">This feature is experimental and subject to change without advance notice.
It will be stabilized and given a backward-compatibility guarantee in a future release,
but may also possibly be removed.</para>
<!-- for a whole manpage --> <!-- for a whole manpage -->
<refsect1 id="component"><title>Experimental</title> <refsect1 id="component"><title>Experimental</title>
<para>This component is experimental and subject to change at any given moment without notice. <para>This component is experimental and subject to change without advance notice.
It will be stabilized and given a backward-compatibility guarantee in a future release.</para> It will be stabilized and given a backward-compatibility guarantee in a future release,
but may also possibly be removed.</para>
</refsect1> </refsect1>
</refsect1> </refsect1>
+1 -2
View File
@@ -435,8 +435,7 @@ sbvarsign --attr "${attr}" --key KEK.key --cert KEK.pem --output db.auth db db.e
<varlistentry> <varlistentry>
<term>reboot-for-bitlocker</term> <term>reboot-for-bitlocker</term>
<listitem><para>Caveat: This feature is experimental, and is likely to be changed (or removed in its <listitem><xi:include href="experimental.xml" xpointer="feature" />
current form) in a future version of systemd.</para>
<para>Work around BitLocker requiring a recovery key when the boot loader was updated (disabled by <para>Work around BitLocker requiring a recovery key when the boot loader was updated (disabled by
default).</para> default).</para>
+2 -1
View File
@@ -320,7 +320,8 @@
<term><option>--profile=<replaceable>PROFILE</replaceable></option></term> <term><option>--profile=<replaceable>PROFILE</replaceable></option></term>
<listitem><para>When attaching an image, select the profile to use. By default, the <literal>default</literal> <listitem><para>When attaching an image, select the profile to use. By default, the <literal>default</literal>
profile is used. For details about profiles, see below.</para> profile is used. Attaching fails if the selected profile does not exist. For details about profiles, see
below.</para>
<xi:include href="version-info.xml" xpointer="v239"/></listitem> <xi:include href="version-info.xml" xpointer="v239"/></listitem>
</varlistentry> </varlistentry>
+15 -7
View File
@@ -32,6 +32,8 @@
<funcdef>int sd_bus_message_append_string_memfd</funcdef> <funcdef>int sd_bus_message_append_string_memfd</funcdef>
<paramdef>sd_bus_message *<parameter>m</parameter></paramdef> <paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
<paramdef>int <parameter>memfd</parameter></paramdef> <paramdef>int <parameter>memfd</parameter></paramdef>
<paramdef>uint64_t <parameter>offset</parameter></paramdef>
<paramdef>uint64_t <parameter>size</parameter></paramdef>
</funcprototype> </funcprototype>
<funcprototype> <funcprototype>
@@ -45,7 +47,7 @@
<funcdef>int sd_bus_message_append_string_space</funcdef> <funcdef>int sd_bus_message_append_string_space</funcdef>
<paramdef>sd_bus_message *<parameter>m</parameter></paramdef> <paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
<paramdef>size_t <parameter>size</parameter></paramdef> <paramdef>size_t <parameter>size</parameter></paramdef>
<paramdef>char **<parameter>s</parameter></paramdef> <paramdef>char **<parameter>ret</parameter></paramdef>
</funcprototype> </funcprototype>
</funcsynopsis> </funcsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@@ -59,11 +61,17 @@
used to append a single string (item of type <literal>s</literal>) used to append a single string (item of type <literal>s</literal>)
to message <parameter>m</parameter>.</para> to message <parameter>m</parameter>.</para>
<para>In case of <para>In case of <function>sd_bus_message_append_string_memfd()</function>, the contents of
<function>sd_bus_message_append_string_memfd()</function>, the <parameter>memfd</parameter> starting at the specified <parameter>offset</parameter> and of the specified
contents of <parameter>memfd</parameter> are the string. They must <parameter>size</parameter> are used as the string. <parameter>size</parameter> must include the
satisfy the same constraints as described for the terminating <constant>NUL</constant> byte, i.e. the resulting string has length
<literal>s</literal> type in <parameter>size</parameter> - 1. If <parameter>offset</parameter> is zero and <parameter>size</parameter>
is <constant>UINT64_MAX</constant>, the full contents of the memory file descriptor are used, and hence
must themselves end in a <constant>NUL</constant> byte. If <parameter>offset</parameter> plus
<parameter>size</parameter> exceeds the actual size of the memory file descriptor, this call fails with
<constant>-EMSGSIZE</constant>. The memory file descriptor is sealed by this call if it has not been
sealed yet, and cannot be modified after this call. The appended contents must satisfy the same
constraints as described for the <literal>s</literal> type in
<citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para> <citerefentry><refentrytitle>sd_bus_message_append_basic</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
<para>In case of <para>In case of
@@ -89,7 +97,7 @@
similar to <function>sd_bus_message_append_basic()</function> with similar to <function>sd_bus_message_append_basic()</function> with
type <literal>s</literal>, but instead of copying a string into type <literal>s</literal>, but instead of copying a string into
the message, it returns a pointer to the destination area to the message, it returns a pointer to the destination area to
the caller in pointer <parameter>p</parameter>. Space for the string the caller in pointer <parameter>ret</parameter>. Space for the string
of length <parameter>size</parameter> plus the terminating of length <parameter>size</parameter> plus the terminating
<constant>NUL</constant> is allocated.</para> <constant>NUL</constant> is allocated.</para>
</refsect1> </refsect1>
+1 -1
View File
@@ -31,7 +31,7 @@
<funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo> <funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
<funcprototype> <funcprototype>
<funcdef>typedef int (*<function>sd_bus_destroy_t</function>)</funcdef> <funcdef>typedef void (*<function>sd_bus_destroy_t</function>)</funcdef>
<paramdef>void *<parameter>userdata</parameter></paramdef> <paramdef>void *<parameter>userdata</parameter></paramdef>
</funcprototype> </funcprototype>
+3
View File
@@ -45,6 +45,9 @@
left" numeric boot counters from the filename, which indicates to future invocations of the boot loader left" numeric boot counters from the filename, which indicates to future invocations of the boot loader
that the entry has completed booting successfully at least once. (This service will hence rename the boot that the entry has completed booting successfully at least once. (This service will hence rename the boot
loader entry file or unified kernel image file on the first successful boot.)</para> loader entry file or unified kernel image file on the first successful boot.)</para>
<para>Note that if the system was booted via kexec and LUO is available and enabled, this service will
skip marking the boot entry as good or bad, since kexec bypasses the EFI boot loader entirely.</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
+2 -3
View File
@@ -26,12 +26,11 @@
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
<xi:include href="experimental.xml" xpointer="component" />
<refsect1> <refsect1>
<title>Description</title> <title>Description</title>
<para>Note: this command is experimental for now. While it is likely to become a regular component of
systemd, it might still change in behaviour and interface.</para>
<para><command>systemd-measure</command> is a tool that may be used to pre-calculate and sign the <para><command>systemd-measure</command> is a tool that may be used to pre-calculate and sign the
expected TPM2 PCR 11 values that should be seen when a Linux <ulink expected TPM2 PCR 11 values that should be seen when a Linux <ulink
url="https://uapi-group.org/specifications/specs/unified_kernel_image/">UAPI.5 Unified Kernel Image url="https://uapi-group.org/specifications/specs/unified_kernel_image/">UAPI.5 Unified Kernel Image
+5 -1
View File
@@ -48,7 +48,11 @@
such as <literal>overlayfs</literal> writes to a separate upper layer that would not be covered by the such as <literal>overlayfs</literal> writes to a separate upper layer that would not be covered by the
checks on the overlay mount itself, mounting a writable <literal>overlayfs</literal> instance is refused checks on the overlay mount itself, mounting a writable <literal>overlayfs</literal> instance is refused
for these user namespaces unless its upper layer, too, is torn down together with the user namespace, or for these user namespaces unless its upper layer, too, is torn down together with the user namespace, or
is an id-mapped mount that translates the transient range away before it reaches the disk.</para> is an id-mapped mount that translates the transient range away before it reaches the disk. The policy
does not cover <literal>cgroupfs</literal>, whose superblock is shared system-wide and cannot be
id-mapped: the only part of it a transient range owns is the cgroup subtree delegated to the user
namespace (see below), which is torn down together with the user namespace, hence user namespaces may
freely create cgroups below it.</para>
<para><command>systemd-nsresourced</command> automatically ensures that any registered UID ranges show up <para><command>systemd-nsresourced</command> automatically ensures that any registered UID ranges show up
in the system's NSS database via the <ulink url="https://systemd.io/USER_GROUP_API">User/Group Record in the system's NSS database via the <ulink url="https://systemd.io/USER_GROUP_API">User/Group Record
+3 -4
View File
@@ -34,12 +34,11 @@
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
<xi:include href="experimental.xml" xpointer="component" />
<refsect1> <refsect1>
<title>Description</title> <title>Description</title>
<para>Note: this command is experimental for now. While it is likely to become a regular component of
systemd, it might still change in behaviour and interface.</para>
<para><command>systemd-pcrlock</command> is a tool that may be used to analyze and predict TPM2 PCR <para><command>systemd-pcrlock</command> is a tool that may be used to analyze and predict TPM2 PCR
measurements, and generate TPM2 access policies from the prediction which it stores in a TPM2 NV index measurements, and generate TPM2 access policies from the prediction which it stores in a TPM2 NV index
(i.e. in the TPM2 non-volatile memory). This may then be used to restrict access to TPM2 objects (such as (i.e. in the TPM2 non-volatile memory). This may then be used to restrict access to TPM2 objects (such as
@@ -273,7 +272,7 @@
currently enforced. This looks at the SecureBoot, PK, KEK, db, dbx, dbt, dbr EFI variables and currently enforced. This looks at the SecureBoot, PK, KEK, db, dbx, dbt, dbr EFI variables and
predicts their measurements to PCR 7 ("secure-boot-policy") on the next boot.</para> predicts their measurements to PCR 7 ("secure-boot-policy") on the next boot.</para>
<para>Use <command>unlock-firmware-config</command> before applying SecureBoot policy updates. If <para>Use <command>unlock-secureboot-policy</command> before applying SecureBoot policy updates. If
the <filename>systemd-pcrlock-secureboot-policy.service</filename> unit is enabled it will the <filename>systemd-pcrlock-secureboot-policy.service</filename> unit is enabled it will
automatically generate a pcrlock file from the policy discovered.</para> automatically generate a pcrlock file from the policy discovered.</para>
+3 -1
View File
@@ -45,7 +45,9 @@
<filename>/usr/local/lib/systemd/report.files/</filename> and <filename>/usr/local/lib/systemd/report.files/</filename> and
<filename>/usr/lib/systemd/report.files/</filename>. Typically these directories contain symlinks pointing <filename>/usr/lib/systemd/report.files/</filename>. Typically these directories contain symlinks pointing
to the actual files in the file system whose contents shall be reported. Entries with the same name in an to the actual files in the file system whose contents shall be reported. Entries with the same name in an
earlier directory override those in a later one.</para> earlier directory override those in a later one. An entry that is a symlink to
<filename>/dev/null</filename> masks the identically named entries in later directories, so that no
metric is reported for that name. Entries that are not regular files are ignored.</para>
<para>Each entry is reported as a metric named <para>Each entry is reported as a metric named
<literal>io.systemd.Files.<replaceable>NAME</replaceable></literal>, where <literal>io.systemd.Files.<replaceable>NAME</replaceable></literal>, where
+2 -3
View File
@@ -30,12 +30,11 @@
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
<xi:include href="experimental.xml" xpointer="component" />
<refsect1> <refsect1>
<title>Description</title> <title>Description</title>
<para><emphasis>Note: this command is experimental for now. While it is likely to become a regular
component of systemd, it might still change in behaviour and interface.</emphasis></para>
<para><command>systemd-report</command> requests metrics from the system and writes them to <para><command>systemd-report</command> requests metrics from the system and writes them to
standard output.</para> standard output.</para>
</refsect1> </refsect1>
+3 -2
View File
@@ -32,6 +32,8 @@
</cmdsynopsis> </cmdsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
<xi:include href="experimental.xml" xpointer="component" />
<refsect1> <refsect1>
<title>Description</title> <title>Description</title>
<para><command>systemd-vmspawn</command> may be used to start a virtual machine from an OS image. In many ways it is similar to <citerefentry> <para><command>systemd-vmspawn</command> may be used to start a virtual machine from an OS image. In many ways it is similar to <citerefentry>
@@ -355,8 +357,7 @@
<varlistentry> <varlistentry>
<term><option>--coco=</option></term> <term><option>--coco=</option></term>
<listitem><para>Caveat: This feature is experimental, and is likely to be changed (or removed in <listitem><xi:include href="experimental.xml" xpointer="feature" />
its current form) in a future version of systemd.</para>
<para>Configures whether to run the guest as a confidential VM. Takes one of <para>Configures whether to run the guest as a confidential VM. Takes one of
<literal>no</literal>, <literal>sev-snp</literal> or <literal>tdx</literal>. Defaults to <literal>no</literal>, <literal>sev-snp</literal> or <literal>tdx</literal>. Defaults to
+8 -1
View File
@@ -1085,6 +1085,10 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
<manvolnum>5</manvolnum></citerefentry>) is typically a better choice than <varname>LimitNPROC=</varname>. <manvolnum>5</manvolnum></citerefentry>) is typically a better choice than <varname>LimitNPROC=</varname>.
</para> </para>
<para>These settings, including the defaults described below, do not affect commands prefixed with
<literal>+</literal>. Such commands inherit the resource limits of the service manager itself, which may be
different.</para>
<para>Resource limits not configured explicitly for a unit default to the value configured in the various <para>Resource limits not configured explicitly for a unit default to the value configured in the various
<varname>DefaultLimitCPU=</varname>, <varname>DefaultLimitFSIZE=</varname>, … options available in <varname>DefaultLimitCPU=</varname>, <varname>DefaultLimitFSIZE=</varname>, … options available in
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>, and – <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>, and –
@@ -2799,7 +2803,10 @@ RestrictNamespaces=~cgroup net</programlisting>
for details about these scheduling policies. Realtime scheduling policies may be used to monopolize CPU for details about these scheduling policies. Realtime scheduling policies may be used to monopolize CPU
time for longer periods of time, and may hence be used to lock up or otherwise trigger Denial-of-Service time for longer periods of time, and may hence be used to lock up or otherwise trigger Denial-of-Service
situations on the system. It is hence recommended to restrict access to realtime scheduling to the few programs situations on the system. It is hence recommended to restrict access to realtime scheduling to the few programs
that actually require them. Defaults to off.</para> that actually require them. Note that the scheduling policy passed to
<citerefentry project='man-pages'><refentrytitle>sched_setattr</refentrytitle><manvolnum>2</manvolnum></citerefentry>
cannot be inspected by the system call filter, hence that system call is refused altogether, including
for non-realtime uses. Defaults to off.</para>
<xi:include href="version-info.xml" xpointer="v231"/></listitem> <xi:include href="version-info.xml" xpointer="v231"/></listitem>
</varlistentry> </varlistentry>
+4 -2
View File
@@ -259,8 +259,10 @@
<listitem> <listitem>
<para>Generators are run very early at boot and cannot rely on any external services. They may not <para>Generators are run very early at boot and cannot rely on any external services. They may not
talk to any other process. That includes simple things such as logging to <citerefentry talk to any other process. That includes simple things such as logging to <citerefentry
project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>, or project='man-pages'><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<command>systemd</command> itself (this means: no <citerefentry
project='man-pages'><refentrytitle>nss</refentrytitle><manvolnum>5</manvolnum></citerefentry> calls
such as <function>getpwnam()</function>, or IPC calls to <command>systemd</command> itself (this means: no
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>)! <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>)!
Non-essential file systems like <filename>/var/</filename> and <filename>/home/</filename> are Non-essential file systems like <filename>/var/</filename> and <filename>/home/</filename> are
mounted after generators have run. Generators can however rely on the most basic kernel functionality mounted after generators have run. Generators can however rely on the most basic kernel functionality
+1 -1
View File
@@ -1576,7 +1576,7 @@ RestartMaxDelaySec=160s</programlisting>
<row> <row>
<entry><literal>+</literal></entry> <entry><literal>+</literal></entry>
<entry>If the executable path is prefixed with <literal>+</literal> then the process is executed with full privileges. In this mode privilege restrictions configured with <varname>User=</varname>, <varname>Group=</varname>, <varname>CapabilityBoundingSet=</varname> or the various file system namespacing options (such as <varname>PrivateDevices=</varname>, <varname>PrivateTmp=</varname>) are not applied to the invoked command line (but still affect any other <varname>ExecStart=</varname>, <varname>ExecStop=</varname>, … lines). However, note that this will not bypass options that apply to the whole control group, such as <varname>DevicePolicy=</varname>, see <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry> for the full list.</entry> <entry>If the executable path is prefixed with <literal>+</literal> then the process is executed with full privileges. In this mode privilege restrictions configured with <varname>User=</varname>, <varname>Group=</varname>, <varname>CapabilityBoundingSet=</varname> or the various file system namespacing options (such as <varname>PrivateDevices=</varname>, <varname>PrivateTmp=</varname>) are not applied to the invoked command line (but still affect any other <varname>ExecStart=</varname>, <varname>ExecStop=</varname>, … lines). Resource limits configured with <varname>LimitCPU=</varname>, <varname>LimitCORE=</varname>, <varname>LimitNOFILE=</varname> and the other resource limit settings described in <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> (including the defaults set with <varname>DefaultLimitCPU=</varname>, <varname>DefaultLimitCORE=</varname>, … in <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>) are not applied either, and the invoked command inherits the resource limits of the service manager itself. However, note that this will not bypass options that apply to the whole control group, such as <varname>DevicePolicy=</varname>, see <citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry> for the full list.</entry>
</row> </row>
<row> <row>
+22
View File
@@ -795,6 +795,28 @@
<xi:include href="version-info.xml" xpointer="v251"/></listitem> <xi:include href="version-info.xml" xpointer="v251"/></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>PartitionZeroFill=</varname></term>
<listitem><para>Takes a boolean. When the target <varname>Type=</varname> is picked as
<constant>partition</constant>, controls whether the remainder of the partition is overwritten with
zeroes after the payload has been written into it. If disabled, only as much of the partition is
written as the payload is large, and whatever data was previously stored in the rest of the partition
remains in place. If enabled, everything from the end of the payload up to the end of the partition
is zeroed out, so that no remnants of an earlier, larger payload survive. On block devices this is
offloaded to the kernel and hence the storage device where possible.</para>
<para>If not specified, defaults to on for Verity signature partitions (i.e. if
<varname>MatchPartitionType=</varname> selects one of the <literal>*-verity-sig</literal> types) and
off for all other partition types. Verity signature partitions carry a JSON object that must be
followed by zero bytes only, up to the end of the partition, while the artifacts installed into them
(for example as generated via the <option>--split=</option> mode of
<citerefentry><refentrytitle>systemd-repart</refentrytitle><manvolnum>8</manvolnum></citerefentry>)
generally do not carry this padding.</para>
<xi:include href="version-info.xml" xpointer="v263"/></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>ReadOnly=</varname></term> <term><varname>ReadOnly=</varname></term>
+20 -19
View File
@@ -236,25 +236,6 @@
<xi:include href="version-info.xml" xpointer="v258"/></listitem> <xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--sign-initrd-pcrs</option></term>
<term><option>--no-sign-initrd-pcrs</option></term>
<listitem><para>Enable or disable signing of additional PCR policies that are bound to the initrd
phase (after <literal>enter-initrd</literal> and before <literal>leave-initrd</literal>) and the
<literal>initrd</literal> policy reference. These additional signed policies are consumed by
<citerefentry><refentrytitle>systemd-tpm2-setup-early.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
to authorize the initialization of NvPCRs. They are also useful for enrolling TPM keyslots to encrypted
volumes that can only be unlocked from the initrd with
<citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
by using the <option>--tpm2-public-key-policyref=initrd</option> option. The extra signatures reuse
the first <varname>PCRPrivateKey=</varname>/<option>--pcr-private-key=</option>, hence one must be
specified, unless <option>--policy-digest</option> is used to generate the policies for offline
signing. Defaults to false.</para>
<xi:include href="version-info.xml" xpointer="v262"/></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--section=<replaceable>NAME</replaceable>:<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></option></term> <term><option>--section=<replaceable>NAME</replaceable>:<replaceable>TEXT</replaceable>|<replaceable>@PATH</replaceable></option></term>
<term><option>--section=<replaceable>NAME</replaceable>:text|binary<optional>@<replaceable>PATH</replaceable></optional></option></term> <term><option>--section=<replaceable>NAME</replaceable>:text|binary<optional>@<replaceable>PATH</replaceable></optional></option></term>
@@ -557,6 +538,26 @@
<xi:include href="version-info.xml" xpointer="v253"/></listitem> <xi:include href="version-info.xml" xpointer="v253"/></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>SignInitrdPCRs=<replaceable>BOOL</replaceable></varname></term>
<term><option>--sign-initrd-pcrs</option></term>
<term><option>--no-sign-initrd-pcrs</option></term>
<listitem><para>Enable or disable signing of additional PCR policies that are bound to the initrd
phase (after <literal>enter-initrd</literal> and before <literal>leave-initrd</literal>) and the
<literal>initrd</literal> policy reference. These additional signed policies are consumed by
<citerefentry><refentrytitle>systemd-tpm2-setup-early.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
to authorize the initialization of NvPCRs. They are also useful for enrolling TPM keyslots to encrypted
volumes that can only be unlocked from the initrd with
<citerefentry><refentrytitle>systemd-cryptenroll</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
by using the <option>--tpm2-public-key-policyref=initrd</option> option. The extra signatures reuse
the first <varname>PCRPrivateKey=</varname>/<option>--pcr-private-key=</option>, hence one must be
specified, unless <option>--policy-digest</option> is used to generate the policies for offline
signing. Defaults to false.</para>
<xi:include href="version-info.xml" xpointer="v262"/></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>SecureBootSigningTool=<replaceable>SIGNER</replaceable></varname></term> <term><varname>SecureBootSigningTool=<replaceable>SIGNER</replaceable></varname></term>
<term><option>--signtool=<replaceable>SIGNER</replaceable></option></term> <term><option>--signtool=<replaceable>SIGNER</replaceable></option></term>
+3 -4
View File
@@ -1028,9 +1028,8 @@ libm = cc.find_library('m')
# On some architectures, libatomic is required. But on some installations, # On some architectures, libatomic is required. But on some installations,
# it is found, but actual linking fails. So let's try to use it opportunistically. # it is found, but actual linking fails. So let's try to use it opportunistically.
# If it is installed, but not needed, it will be dropped because of --as-needed. # If it is installed, but not needed, it will be dropped because of --as-needed.
if cc.links('''int main(int argc, char **argv) { return 0; }''', basic_c_prog = '''int main(int argc, char **argv) { return 0; }'''
args : '-latomic', if cc.links(basic_c_prog, args : '-latomic', name : 'libatomic')
name : 'libatomic')
libatomic = declare_dependency(link_args : '-latomic') libatomic = declare_dependency(link_args : '-latomic')
else else
libatomic = [] libatomic = []
@@ -1760,7 +1759,7 @@ have = get_option('bootloader').require(
pyelftools.found() and get_option('efi') and efi_arch != '', pyelftools.found() and get_option('efi') and efi_arch != '',
error_message : 'unsupported EFI arch or EFI support is disabled').allowed() error_message : 'unsupported EFI arch or EFI support is disabled').allowed()
conf.set10('ENABLE_BOOTLOADER', have) conf.set10('ENABLE_BOOTLOADER', have)
conf.set_quoted('EFI_MACHINE_TYPE_NAME', have ? efi_arch : '') conf.set_quoted('EFI_MACHINE_TYPE_NAME', efi_arch)
efi_arch_alt = '' efi_arch_alt = ''
efi_cpu_family_alt = '' efi_cpu_family_alt = ''
+1 -1
View File
@@ -1 +1 @@
262 262.1
+1 -1
View File
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
[Config] [Config]
MinimumVersion=commit:f7762b71437227922a367bb89597843c77494ef9 MinimumVersion=commit:71d7b67e01dc47ab5c51f24866c3e2195b9701d2
Dependencies= Dependencies=
minimal-base minimal-base
minimal-0 minimal-0
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
[Match] [Match]
Distribution=postmarketos Distribution=nura
[Distribution] [Distribution]
Release=edge Release=edge
@@ -1,4 +1,4 @@
# postmarketOS does not support userdbd, so creating the test user via # Nura does not support userdbd, so creating the test user via
# userdbd credentials does not work. We need to create the user entries # userdbd credentials does not work. We need to create the user entries
# in /etc/passwd and /etc/group using sysusers instead. # in /etc/passwd and /etc/group using sysusers instead.
u testuser 4711 testuser /home/testuser /bin/bash u testuser 4711 testuser /home/testuser /bin/bash
@@ -1,4 +1,4 @@
# postmarketOS does not support userdbd, so creating the test user via # Nura does not support userdbd, so creating the test user via
# userdbd credentials does not work. We need to create the user's home # userdbd credentials does not work. We need to create the user's home
# directory using tmpfiles instead. # directory using tmpfiles instead.
Q /home/testuser 0700 testuser testuser - - Q /home/testuser 0700 testuser testuser - -
@@ -19,7 +19,7 @@ enable systemd-networkd-wait-online.service
# systemd-resolved is disabled by default on CentOS so make sure it is enabled. # systemd-resolved is disabled by default on CentOS so make sure it is enabled.
enable systemd-resolved.service enable systemd-resolved.service
# systemd-time-wait-sync.service is enabled by default on postmarketOS. # systemd-time-wait-sync.service is enabled by default on Nura.
# It pulls in time-sync.target, but the target is never reached because the # It pulls in time-sync.target, but the target is never reached because the
# test environment has no Internet connectivity. As a result, timer units # test environment has no Internet connectivity. As a result, timer units
# cannot be started. Disable the service explicitly to allow timer units to # cannot be started. Disable the service explicitly to allow timer units to
@@ -69,11 +69,11 @@ disable multipathd.service
# https://github.com/opensvc/multipath-tools/commit/346e9adda4e5f0ccfcbb7a3eccf5f96001d95027 # https://github.com/opensvc/multipath-tools/commit/346e9adda4e5f0ccfcbb7a3eccf5f96001d95027
disable multipathd.socket disable multipathd.socket
# rtkit-daemon.service randomly fails with the following error on postmarketOS: # rtkit-daemon.service randomly fails with the following error on Nura:
# rtkit-daemon[54]: pthread_create failed: Resource temporarily unavailable # rtkit-daemon[54]: pthread_create failed: Resource temporarily unavailable
# The service is not necessary on our test suites, let's disable it. # The service is not necessary on our test suites, let's disable it.
disable rtkit-daemon.service disable rtkit-daemon.service
# Disable postmarketOS specific zram swap service. # Disable Nura specific zram swap service.
# Maybe better to replace it with zram-generator? # Maybe better to replace it with zram-generator?
disable zram_swap.service disable zram_swap.service
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
[Match] [Match]
Distribution=postmarketos Distribution=nura
[Content] [Content]
Packages= Packages=
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
[Match] [Match]
Distribution=postmarketos Distribution=nura
[Content] [Content]
Packages= Packages=
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
[Match] [Match]
Distribution=postmarketos Distribution=nura
[Content] [Content]
Packages= Packages=
@@ -9,7 +9,6 @@ Packages=
coreutils coreutils
device-mapper device-mapper
e2fsprogs e2fsprogs
musl-utils
tpm2-tools tpm2-tools
# For TEST-92-TPM2-SWTPM, install following packages when # For TEST-92-TPM2-SWTPM, install following packages when
# https://github.com/systemd/systemd/pull/42760 # https://github.com/systemd/systemd/pull/42760
+1 -1
View File
@@ -7,5 +7,5 @@ Distribution=arch
Environment= Environment=
GIT_URL=https://gitlab.archlinux.org/archlinux/packaging/packages/systemd.git GIT_URL=https://gitlab.archlinux.org/archlinux/packaging/packages/systemd.git
GIT_BRANCH=main GIT_BRANCH=main
GIT_COMMIT=f884cb080300eeb273fb7549fd0aa19bb6142c21 GIT_COMMIT=4749b653ee7b9210bcd46fe43065508aa58b779a
PKG_SUBDIR=arch PKG_SUBDIR=arch
@@ -8,6 +8,6 @@ Distribution=|ubuntu
Environment= Environment=
GIT_URL=https://salsa.debian.org/systemd-team/systemd.git GIT_URL=https://salsa.debian.org/systemd-team/systemd.git
GIT_SUBDIR=debian GIT_SUBDIR=debian
GIT_BRANCH=debian/master GIT_BRANCH=ci/v262-stable
GIT_COMMIT=70dd6c36578ecaa214992f54701eeedaa3b57aed GIT_COMMIT=1977fb1ce434103e4ff5355cf5d68593c65db204
PKG_SUBDIR=debian PKG_SUBDIR=debian
@@ -1,12 +1,12 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
[Match] [Match]
Distribution=postmarketos Distribution=nura
[Build] [Build]
Environment= Environment=
GIT_URL=https://gitlab.postmarketos.org/postmarketOS/pmaports GIT_URL=https://gitlab.postmarketos.org/postmarketOS/pmaports
GIT_SUBDIR=extra-repos/systemd/systemd GIT_SUBDIR=extra-repos/systemd/systemd
GIT_BRANCH=main GIT_BRANCH=main
GIT_COMMIT=bd970948e652e16e8ef8688cc891aa5ab80dbaa3 GIT_COMMIT=7a6b81a4f1a7a510d088a5874bebcf2b200b69b3
PKG_SUBDIR=postmarketos PKG_SUBDIR=nura
@@ -7,11 +7,6 @@ Distribution=fedora
Packages= Packages=
gh gh
lcov lcov
libgcrypt-devel
libgpg-error-devel
musl-libc
musl-clang
musl-gcc
ruff ruff
coccinelle coccinelle
shellcheck shellcheck
@@ -1,10 +1,10 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
[Match] [Match]
Distribution=postmarketos Distribution=nura
[Content] [Content]
PrepareScripts=%D/mkosi/mkosi.images/build/mkosi.conf.d/postmarketos/mkosi.prepare PrepareScripts=%D/mkosi/mkosi.images/build/mkosi.conf.d/nura/mkosi.prepare
Packages= Packages=
alpine-sdk alpine-sdk
postmarketos-base postmarketos-base
+2 -1
View File
@@ -1,7 +1,8 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
# The mixed case ID checks that entry IDs are matched case insensitively.
[UKIProfile] [UKIProfile]
Profile= Profile=
ID=profile2 ID=Profile2
TITLE=Profile Two TITLE=Profile Two
Cmdline=testprofile2=1 Cmdline=testprofile2=1
+2 -2
View File
@@ -177,8 +177,8 @@ static void plot_tooltip(const UnitTimes *ut) {
assert(ut->name); assert(ut->name);
svg("%s:\n", ut->name); svg("%s:\n", ut->name);
svg("Activating: %"PRI_USEC".%.3"PRI_USEC"\n", ut->activating / USEC_PER_SEC, ut->activating % USEC_PER_SEC); svg("Activating: %"PRI_USEC".%.6"PRI_USEC"\n", ut->activating / USEC_PER_SEC, ut->activating % USEC_PER_SEC);
svg("Activated: %"PRI_USEC".%.3"PRI_USEC"\n", ut->activated / USEC_PER_SEC, ut->activated % USEC_PER_SEC); svg("Activated: %"PRI_USEC".%.6"PRI_USEC"\n", ut->activated / USEC_PER_SEC, ut->activated % USEC_PER_SEC);
UnitDependency i; UnitDependency i;
FOREACH_ARGUMENT(i, UNIT_AFTER, UNIT_BEFORE, UNIT_REQUIRES, UNIT_REQUISITE, UNIT_WANTS, UNIT_CONFLICTS, UNIT_UPHOLDS) FOREACH_ARGUMENT(i, UNIT_AFTER, UNIT_BEFORE, UNIT_REQUIRES, UNIT_REQUISITE, UNIT_WANTS, UNIT_CONFLICTS, UNIT_UPHOLDS)
+17
View File
@@ -206,6 +206,23 @@ bool cg_kill_supported(void) {
return (supported = false); return (supported = false);
} }
/* ANCIENT-MOD: cgroup v2 freezer is available since kernel 5.2 */
bool cg_freezer_supported(void) {
static thread_local int supported = -1;
if (supported >= 0)
return supported;
if (cg_is_available() <= 0)
return (supported = false);
if (access("/sys/fs/cgroup/init.scope/cgroup.freeze", F_OK) >= 0)
return (supported = true);
if (errno != ENOENT)
log_debug_errno(errno, "Failed to check whether cgroup freezer is available, assuming not: %m");
return (supported = false);
}
int cg_enumerate_subgroups(const char *path, DIR **ret) { int cg_enumerate_subgroups(const char *path, DIR **ret) {
_cleanup_free_ char *fs = NULL; _cleanup_free_ char *fs = NULL;
DIR *d; DIR *d;
+1
View File
@@ -235,6 +235,7 @@ int cg_mask_from_string(const char *s, CGroupMask *ret);
int cg_mask_to_string(CGroupMask mask, char **ret); int cg_mask_to_string(CGroupMask mask, char **ret);
bool cg_kill_supported(void); bool cg_kill_supported(void);
bool cg_freezer_supported(void);
DECLARE_STRING_TABLE_LOOKUP(cgroup_controller, CGroupController); DECLARE_STRING_TABLE_LOOKUP(cgroup_controller, CGroupController);
+2 -2
View File
@@ -286,8 +286,8 @@ int chaseat(int root_fd, int dir_fd, const char *path, ChaseFlags flags, char **
* 2. With ret_fd: in this case the destination is opened after chasing it as O_PATH and this file * 2. With ret_fd: in this case the destination is opened after chasing it as O_PATH and this file
* descriptor is returned as return value. This is useful to open files relative to some root * descriptor is returned as return value. This is useful to open files relative to some root
* directory. Note that the returned O_PATH file descriptors must be converted into a regular one * directory. Note that the returned O_PATH file descriptors must be converted into a regular one
* (using fd_reopen() or such) before it can be used for reading/writing. ret_fd may not be * (using fd_reopen() or such) before it can be used for reading/writing. If CHASE_NONEXISTENT
* combined with CHASE_NONEXISTENT. * is also set and the destination doesn't exist, 0 is returned and ret_fd is set to -EBADF.
* *
* 3. With CHASE_STEP: in this case only a single step of the normalization is executed, i.e. only * 3. With CHASE_STEP: in this case only a single step of the normalization is executed, i.e. only
* the first symlink or ".." component of the path is resolved, and the resulting path is * the first symlink or ".." component of the path is resolved, and the resulting path is
+7 -1
View File
@@ -2171,8 +2171,14 @@ int decompressor_push(Decompressor *c, const void *data, size_t size, Decompress
c->gzip.next_out = buffer; c->gzip.next_out = buffer;
c->gzip.avail_out = COMPRESS_PIPE_BUFFER_SIZE; c->gzip.avail_out = COMPRESS_PIPE_BUFFER_SIZE;
/* Z_BUF_ERROR is not fatal if all input is used up: it just means no progress was
* possible, which happens if the previous iteration filled the output buffer exactly
* while also consuming all input. That case is handled by the avail_in check
* below. If there's still input left however, Z_BUF_ERROR means we are stuck, hence
* refuse it, so that we don't loop forever. */
int zr = sym_inflate(&c->gzip, Z_NO_FLUSH); int zr = sym_inflate(&c->gzip, Z_NO_FLUSH);
if (!IN_SET(zr, Z_OK, Z_STREAM_END)) if (!IN_SET(zr, Z_OK, Z_STREAM_END) &&
!(zr == Z_BUF_ERROR && c->gzip.avail_in == 0))
return -EBADMSG; return -EBADMSG;
if (c->gzip.avail_out > COMPRESS_PIPE_BUFFER_SIZE) if (c->gzip.avail_out > COMPRESS_PIPE_BUFFER_SIZE)
+80 -16
View File
@@ -260,9 +260,10 @@ int close_all_fds_frugal(const int except[], size_t n_except) {
assert(except || n_except == 0); assert(except || n_except == 0);
/* This is the inner fallback core of close_all_fds(). This never calls malloc() or so and hence is /* This is the inner fallback core of close_all_fds(). This never calls malloc() or opendir() or so
* safe to be called in signal handler context. Most users should call close_all_fds(), but when we * and hence is safe to be called in signal handler context. Most users should call close_all_fds(),
* assume we are called from signal handler context, then use this simpler call instead. */ * but when we assume we are called from signal handler context, then use this simpler call
* instead. */
max_fd = get_max_fd(); max_fd = get_max_fd();
if (max_fd < 0) if (max_fd < 0)
@@ -288,6 +289,44 @@ int close_all_fds_frugal(const int except[], size_t n_except) {
return r; return r;
} }
int close_all_fds_by_proc(const int except[], size_t n_except) {
_cleanup_closedir_ DIR *d = NULL;
int r = 0;
d = opendir("/proc/self/fd");
if (!d)
return close_all_fds_frugal(except, n_except); /* ultimate fallback if /proc/ is not available */
FOREACH_DIRENT(de, d, return -errno) {
int fd = -EBADF, q;
if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
continue;
fd = parse_fd(de->d_name);
if (fd < 0)
/* Let's better ignore this, just in case */
continue;
if (fd < 3)
continue;
if (fd == dirfd(d))
continue;
if (fd_in_set(fd, except, n_except))
continue;
q = close_nointr(fd);
if (q != -EBADF) /* Valgrind has its own FD and doesn't want to have it closed */
RET_GATHER(r, q);
}
return r;
}
static bool have_close_range = true; /* Assume we live in the future */
static int close_all_fds_special_case(const int except[], size_t n_except) { static int close_all_fds_special_case(const int except[], size_t n_except) {
assert(n_except == 0 || except); assert(n_except == 0 || except);
@@ -295,6 +334,9 @@ static int close_all_fds_special_case(const int except[], size_t n_except) {
* nicely, since we won't need sorting for them. Returns > 0 if the special casing worked, 0 * nicely, since we won't need sorting for them. Returns > 0 if the special casing worked, 0
* otherwise. */ * otherwise. */
if (!have_close_range)
return 0;
if (n_except == 1 && except[0] < 0) /* Minor optimization: if we only got one fd, and it's invalid, if (n_except == 1 && except[0] < 0) /* Minor optimization: if we only got one fd, and it's invalid,
* we got none */ * we got none */
n_except = 0; n_except = 0;
@@ -303,22 +345,31 @@ static int close_all_fds_special_case(const int except[], size_t n_except) {
case 0: case 0:
/* Close everything. Yay! */ /* Close everything. Yay! */
if (close_range(3, INT_MAX, 0) < 0)
return -errno;
return 1; if (close_range(3, INT_MAX, 0) >= 0)
return 1;
if (ERRNO_IS_NOT_SUPPORTED(errno) || ERRNO_IS_PRIVILEGE(errno)) {
have_close_range = false;
return 0;
}
return -errno;
case 1: case 1:
/* Close all but exactly one, then we don't need no sorting. This is a pretty common /* Close all but exactly one, then we don't need no sorting. This is a pretty common
* case, hence let's handle it specially. */ * case, hence let's handle it specially. */
if (except[0] > 3 && close_range(3, except[0] - 1, 0) < 0) if ((except[0] <= 3 || close_range(3, except[0]-1, 0) >= 0) &&
return -errno; (except[0] >= INT_MAX || close_range(MAX(3, except[0]+1), -1, 0) >= 0))
return 1;
if (except[0] < INT_MAX && close_range(MAX(3, except[0] + 1), -1, 0) < 0) if (ERRNO_IS_NOT_SUPPORTED(errno) || ERRNO_IS_PRIVILEGE(errno)) {
return -errno; have_close_range = false;
return 0;
}
return 1; return -errno;
default: default:
return 0; return 0;
@@ -350,6 +401,9 @@ int close_all_fds(const int except[], size_t n_except) {
if (r > 0) /* special case worked! */ if (r > 0) /* special case worked! */
return 0; return 0;
if (!have_close_range)
return close_all_fds_by_proc(except, n_except);
_cleanup_free_ int *sorted_malloc = NULL; _cleanup_free_ int *sorted_malloc = NULL;
size_t n_sorted; size_t n_sorted;
int *sorted; int *sorted;
@@ -369,7 +423,7 @@ int close_all_fds(const int except[], size_t n_except) {
sorted = newa(int, n_sorted); sorted = newa(int, n_sorted);
if (!sorted) /* Fallback on OOM. */ if (!sorted) /* Fallback on OOM. */
return close_all_fds_frugal(except, n_except); return close_all_fds_by_proc(except, n_except);
memcpy(sorted, except, n_except * sizeof(int)); memcpy(sorted, except, n_except * sizeof(int));
@@ -391,8 +445,13 @@ int close_all_fds(const int except[], size_t n_except) {
continue; continue;
/* Close everything between the start and end fds (both of which shall stay open) */ /* Close everything between the start and end fds (both of which shall stay open) */
if (close_range(start + 1, end - 1, 0) < 0) if (close_range(start + 1, end - 1, 0) < 0) {
return -errno; if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
return -errno;
have_close_range = false;
return close_all_fds_by_proc(except, n_except);
}
} }
/* The loop succeeded. Let's now close everything beyond the end */ /* The loop succeeded. Let's now close everything beyond the end */
@@ -400,8 +459,13 @@ int close_all_fds(const int except[], size_t n_except) {
if (sorted[n_sorted-1] >= INT_MAX) /* Dont let the addition below overflow */ if (sorted[n_sorted-1] >= INT_MAX) /* Dont let the addition below overflow */
return 0; return 0;
if (close_range(sorted[n_sorted-1] + 1, INT_MAX, 0) < 0) if (close_range(sorted[n_sorted-1] + 1, INT_MAX, 0) < 0) {
return -errno; if (!ERRNO_IS_NOT_SUPPORTED(errno) && !ERRNO_IS_PRIVILEGE(errno))
return -errno;
have_close_range = false;
return close_all_fds_by_proc(except, n_except);
}
return 0; return 0;
} }
+1
View File
@@ -127,6 +127,7 @@ int get_max_fd(void);
int close_all_fds(const int except[], size_t n_except); int close_all_fds(const int except[], size_t n_except);
int close_all_fds_without_malloc(const int except[], size_t n_except); int close_all_fds_without_malloc(const int except[], size_t n_except);
int close_all_fds_by_proc(const int except[], size_t n_except);
int close_all_fds_frugal(const int except[], size_t n_except); int close_all_fds_frugal(const int except[], size_t n_except);
int pack_fds(int fds[], size_t n); int pack_fds(int fds[], size_t n);
+28 -2
View File
@@ -322,7 +322,20 @@ int futimens_opath(int fd, const struct timespec ts[2]) {
assert(fd >= 0); assert(fd >= 0);
return RET_NERRNO(utimensat(fd, "", ts, AT_EMPTY_PATH)); if (utimensat(fd, "", ts, AT_EMPTY_PATH) >= 0)
return 0;
if (errno != EINVAL)
return -errno;
/* ANCIENT-MOD: AT_EMPTY_PATH is supported since kernel 5.8, fall back to /proc/self/fd/ */
if (utimensat(AT_FDCWD, FORMAT_PROC_FD_PATH(fd), ts, /* flags= */ 0) < 0) {
if (errno != ENOENT)
return -errno;
return proc_fd_enoent_errno();
}
return 0;
} }
int stat_warn_permissions(const char *path, const struct stat *st) { int stat_warn_permissions(const char *path, const struct stat *st) {
@@ -371,7 +384,20 @@ int access_fd(int fd, int mode) {
assert(fd >= 0); assert(fd >= 0);
return RET_NERRNO(faccessat(fd, "", mode, AT_EMPTY_PATH)); if (faccessat(fd, "", mode, AT_EMPTY_PATH) >= 0)
return 0;
if (errno != EINVAL)
return -errno;
/* ANCIENT-MOD: AT_EMPTY_PATH is supported since kernel 5.8, fall back to /proc/self/fd/ */
if (access(FORMAT_PROC_FD_PATH(fd), mode) < 0) {
if (errno != ENOENT)
return -errno;
return proc_fd_enoent_errno();
}
return 0;
} }
int touch_fd(int fd, usec_t stamp) { int touch_fd(int fd, usec_t stamp) {
+50
View File
@@ -11,6 +11,7 @@
#include "errno-util.h" #include "errno-util.h"
#include "fiber-ops.h" #include "fiber-ops.h"
#include "io-util.h" #include "io-util.h"
#include "iovec-util.h"
#include "time-util.h" #include "time-util.h"
uint32_t poll_events_to_epoll(uint32_t events) { uint32_t poll_events_to_epoll(uint32_t events) {
@@ -249,6 +250,55 @@ int loop_write_full(int fd, const void *buf, size_t nbytes, usec_t timeout) {
return 0; return 0;
} }
int pwritev_full(int fd, struct iovec *iovec, size_t n, uint64_t offset, uint64_t *ret_written) {
uint64_t written = 0;
int r = 0;
assert(fd >= 0);
assert(iovec || n == 0);
/* Writes all of the iovecs at the offset. The iovecs are advanced past what was written, and
* 'ret_written' tells how much that was, also if the write fails halfway. */
for (size_t i = 0;;) {
size_t m;
ssize_t k;
while (i < n && !iovec_is_set(iovec + i))
i++;
if (i >= n)
break;
m = MIN(n - i, (size_t) IOV_MAX);
k = pwritev(fd, iovec + i, m, offset + written);
if (k < 0) {
if (errno == EINTR)
continue;
r = -errno;
break;
}
if (k == 0) {
r = -EIO;
break;
}
written += k;
(void) iovec_inc_many(iovec + i, m, k);
}
if (ret_written)
*ret_written = written;
return r;
}
int pwrite_full(int fd, const void *buf, size_t nbytes, uint64_t offset) {
assert(fd >= 0);
assert(buf || nbytes == 0);
return pwritev_full(fd, &IOVEC_MAKE((void*) buf, nbytes), 1, offset, /* ret_written= */ NULL);
}
int pipe_eof(int fd) { int pipe_eof(int fd) {
int r; int r;
+3
View File
@@ -20,6 +20,9 @@ static inline int loop_write(int fd, const void *buf, size_t nbytes) {
return loop_write_full(fd, buf, nbytes, 0); return loop_write_full(fd, buf, nbytes, 0);
} }
int pwritev_full(int fd, struct iovec *iovec, size_t n, uint64_t offset, uint64_t *ret_written);
int pwrite_full(int fd, const void *buf, size_t nbytes, uint64_t offset) _nonnull_if_nonzero_(2, 3);
int pipe_eof(int fd); int pipe_eof(int fd);
int ppoll_usec_full(struct pollfd *fds, size_t n_fds, usec_t timeout, const sigset_t *ss) _nonnull_if_nonzero_(1, 2); int ppoll_usec_full(struct pollfd *fds, size_t n_fds, usec_t timeout, const sigset_t *ss) _nonnull_if_nonzero_(1, 2);
+36 -22
View File
@@ -56,16 +56,11 @@ static char* normalize_locale(const char *name) {
return strdup(name); return strdup(name);
} }
static const char* get_locale_dir(void) {
return secure_getenv("SYSTEMD_LOCALE_DIRECTORY") ?:
#ifdef __GLIBC__ #ifdef __GLIBC__
"/usr/lib/locale/"; static const char* get_locale_dir(void) {
#else return secure_getenv("SYSTEMD_LOCALE_DIRECTORY") ?: "/usr/lib/locale/";
"/usr/share/i18n/locales/musl/";
#endif
} }
#ifdef __GLIBC__
static int add_locales_from_archive(Set *locales) { static int add_locales_from_archive(Set *locales) {
/* Stolen from glibc... */ /* Stolen from glibc... */
@@ -201,26 +196,38 @@ static int add_locales_from_libdir(Set *locales) {
#else #else
static const char* const musl_locale_dirs[] = {
"/etc/musl/locale",
"/usr/share/musl/locale",
"/share/musl/locale",
"/usr/share/i18n/locales/musl", // compat with musl-locales 0.1.0
NULL
};
static int add_locales_for_musl(Set *locales) { static int add_locales_for_musl(Set *locales) {
int r; int r;
assert(locales); assert(locales);
_cleanup_closedir_ DIR *dir = opendir(get_locale_dir()); const char *e = secure_getenv("SYSTEMD_LOCALE_DIRECTORY");
if (!dir)
return errno == ENOENT ? 0 : -errno;
FOREACH_DIRENT(de, dir, return -errno) { STRV_FOREACH(d, e ? STRV_MAKE_CONST(e) : musl_locale_dirs) {
if (de->d_type != DT_REG) _cleanup_closedir_ DIR *dir = opendir(*d);
if (!dir)
continue; continue;
char *z = normalize_locale(de->d_name); FOREACH_DIRENT(de, dir, return -errno) {
if (!z) if (de->d_type != DT_REG)
return -ENOMEM; continue;
r = set_consume(locales, z); char *z = normalize_locale(de->d_name);
if (r < 0) if (!z)
return r; return -ENOMEM;
r = set_consume(locales, z);
if (r < 0)
return r;
}
} }
return 0; return 0;
@@ -330,11 +337,18 @@ int locale_is_installed(const char *name) {
/* musl's newlocale() always succeeds and provides a fake locale object even when the locale does /* musl's newlocale() always succeeds and provides a fake locale object even when the locale does
* not exist. Hence, we need to explicitly check if the locale file exists. */ * not exist. Hence, we need to explicitly check if the locale file exists. */
_cleanup_free_ char *p = path_join(get_locale_dir(), name); const char *e = secure_getenv("SYSTEMD_LOCALE_DIRECTORY");
if (!p)
return -ENOMEM;
return access(p, F_OK) >= 0; STRV_FOREACH(d, e ? STRV_MAKE_CONST(e) : musl_locale_dirs) {
_cleanup_free_ char *p = path_join(*d, name);
if (!p)
return -ENOMEM;
if (access(p, F_OK) >= 0)
return true;
}
return false;
#endif #endif
} }
+22 -6
View File
@@ -7,6 +7,7 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "errno-util.h" #include "errno-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "io-util.h"
#include "memfd-util.h" #include "memfd-util.h"
#include "process-util.h" #include "process-util.h"
#include "string-util.h" #include "string-util.h"
@@ -95,10 +96,27 @@ int memfd_get_sealed(int fd) {
if (r < 0) if (r < 0)
return r; return r;
/* We ignore F_SEAL_EXEC here to support older kernels. */ /* We ignore F_SEAL_EXEC here to support older kernels.
* It is supported since kernel v6.3 (6fd7353829cafc4067aad9eea0dc95da67e7df16). */
return FLAGS_SET(seals, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE); return FLAGS_SET(seals, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE);
} }
int memfd_set_sealed_gracefully(int fd) {
int r;
r = memfd_set_sealed(fd);
if (r != -EPERM)
return r;
/* Already sealed? Check if required seals are set. */
r = memfd_get_sealed(fd);
if (r < 0)
return r;
if (r == 0)
return -EPERM; /* Propagate the original error. */
return 0;
}
int memfd_get_size(int fd, uint64_t *ret) { int memfd_get_size(int fd, uint64_t *ret) {
struct stat stat; struct stat stat;
@@ -132,11 +150,9 @@ int memfd_new_and_seal(const char *name, const void *data, size_t sz) {
return fd; return fd;
if (sz > 0) { if (sz > 0) {
ssize_t n = pwrite(fd, data, sz, 0); r = pwrite_full(fd, data, sz, 0);
if (n < 0) if (r < 0)
return -errno; return r;
if ((size_t) n != sz)
return -EIO;
} }
r = memfd_set_sealed(fd); r = memfd_set_sealed(fd);
+1
View File
@@ -19,6 +19,7 @@ static inline int memfd_new_and_seal_string(const char *name, const char *s) {
int memfd_set_sealed(int fd); int memfd_set_sealed(int fd);
int memfd_get_sealed(int fd); int memfd_get_sealed(int fd);
int memfd_set_sealed_gracefully(int fd);
int memfd_get_size(int fd, uint64_t *ret); int memfd_get_size(int fd, uint64_t *ret);
int memfd_set_size(int fd, uint64_t sz); int memfd_set_size(int fd, uint64_t sz);
+2
View File
@@ -681,6 +681,8 @@ int mount_option_supported(const char *fstype, const char *key, const char *valu
if (fd < 0) { if (fd < 0) {
if (errno == ENODEV) if (errno == ENODEV)
return log_debug_errno(errno, "Kernel does not support file system type '%s'.", fstype); return log_debug_errno(errno, "Kernel does not support file system type '%s'.", fstype);
if (ERRNO_IS_NOT_SUPPORTED(errno))
return -EAGAIN; /* ANCIENT-MOD: new mount API not available (kernel < 5.2) → don't know */
return log_debug_errno(errno, "Failed to open superblock context for '%s': %m", fstype); return log_debug_errno(errno, "Failed to open superblock context for '%s': %m", fstype);
} }
+6 -5
View File
@@ -300,15 +300,16 @@ int namespace_enter_full(
/* If we don't have CAP_SYS_ADMIN in our own user namespace, our best bet is to enter the /* If we don't have CAP_SYS_ADMIN in our own user namespace, our best bet is to enter the
* user namespace first (if we got one) to get CAP_SYS_ADMIN within the child user namespace, * user namespace first (if we got one) to get CAP_SYS_ADMIN within the child user namespace,
* and then hope the other namespaces are owned by the child user namespace. If they aren't, * and then hope the other namespaces are owned by the child user namespace. If they aren't,
* we'll just get an EPERM later on when trying to setns() to them. */ * we'll just get an EPERM later on when trying to setns() to them. If there's no namespace
* left to join, there's nothing to need privileges for. */
if (userns_fd < 0) if (userns_fd >= 0) {
if (setns(userns_fd, CLONE_NEWUSER) < 0)
return -errno;
} else if (pidns_fd >= 0 || mntns_fd >= 0 || netns_fd >= 0 || root_fd >= 0)
return log_debug_errno( return log_debug_errno(
SYNTHETIC_ERRNO(EPERM), SYNTHETIC_ERRNO(EPERM),
"Need CAP_SYS_ADMIN or a child user namespace to enter namespaces."); "Need CAP_SYS_ADMIN or a child user namespace to enter namespaces.");
if (setns(userns_fd, CLONE_NEWUSER) < 0)
return -errno;
} }
if (pidns_fd >= 0) if (pidns_fd >= 0)
+10 -2
View File
@@ -28,8 +28,11 @@ int pidfd_check_pidfs(int pid_fd) {
_cleanup_close_ int our_fd = -EBADF; _cleanup_close_ int our_fd = -EBADF;
if (pid_fd < 0) { if (pid_fd < 0) {
our_fd = pidfd_open(getpid_cached(), /* flags= */ 0); our_fd = pidfd_open(getpid_cached(), /* flags= */ 0);
if (our_fd < 0) if (our_fd < 0) {
if (ERRNO_IS_NOT_SUPPORTED(errno)) /* ANCIENT-MOD: kernel < 5.3 */
return (have_pidfs = false);
return -errno; return -errno;
}
pid_fd = our_fd; pid_fd = our_fd;
} }
@@ -102,6 +105,8 @@ int pidfd_info_mask_is_supported(uint64_t mask) {
if (cached == 0) { if (cached == 0) {
_cleanup_close_ int pidfd = r = RET_NERRNO(pidfd_open(getpid_cached(), /* flags= */ 0)); _cleanup_close_ int pidfd = r = RET_NERRNO(pidfd_open(getpid_cached(), /* flags= */ 0));
if (ERRNO_IS_NEG_NOT_SUPPORTED(r)) /* ANCIENT-MOD: kernel < 5.3 */
return (cached = -EOPNOTSUPP);
if (r < 0) if (r < 0)
return r; return r;
@@ -334,8 +339,11 @@ int pidfd_get_inode_id_self_cached(uint64_t *ret) {
return initialized; return initialized;
_cleanup_close_ int fd = pidfd_open(getpid_cached(), 0); _cleanup_close_ int fd = pidfd_open(getpid_cached(), 0);
if (fd < 0) if (fd < 0) {
if (ERRNO_IS_NOT_SUPPORTED(errno)) /* ANCIENT-MOD: kernel < 5.3 */
return (initialized = -EOPNOTSUPP);
return -errno; return -errno;
}
r = pidfd_get_inode_id(fd, &cached); r = pidfd_get_inode_id(fd, &cached);
if (ERRNO_IS_NEG_NOT_SUPPORTED(r)) if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
+28 -9
View File
@@ -106,9 +106,10 @@ int pidref_set_pid_full(PidRef *pidref, pid_t pid, unsigned flags) {
fd = pidfd_open(pid, flags); fd = pidfd_open(pid, flags);
if (fd < 0) { if (fd < 0) {
/* Graceful fallback in case the kernel is out of fds. /* Graceful fallback in case the kernel is out of fds or lacks pidfd_open() (ANCIENT-MOD: < 5.3).
* The PIDFD_THREAD flag is supported since kernel v6.9 (64bef697d33b75fc06c5789b3f8108680271529f). */ * The PIDFD_THREAD flag is supported since kernel v6.9 (64bef697d33b75fc06c5789b3f8108680271529f). */
if (!(ERRNO_IS_RESOURCE(errno) || (errno == EINVAL && FLAGS_SET(flags, PIDFD_THREAD)))) if (!(ERRNO_IS_RESOURCE(errno) || ERRNO_IS_NOT_SUPPORTED(errno) ||
(errno == EINVAL && FLAGS_SET(flags, PIDFD_THREAD))))
return log_debug_errno(errno, "Failed to open pidfd for pid " PID_FMT ": %m", pid); return log_debug_errno(errno, "Failed to open pidfd for pid " PID_FMT ": %m", pid);
fd = -EBADF; fd = -EBADF;
@@ -468,16 +469,34 @@ int pidref_wait_for_terminate_full(PidRef *pidref, usec_t timeout, siginfo_t *re
if (pidref->pid == 1 || pidref_is_self(pidref)) if (pidref->pid == 1 || pidref_is_self(pidref))
return -ECHILD; return -ECHILD;
if (pidref->fd < 0 && (timeout != USEC_INFINITY || fiber_ops_is_set()))
return -ENOMEDIUM;
usec_t ts = timeout == USEC_INFINITY ? USEC_INFINITY : usec_add(now(CLOCK_MONOTONIC), timeout); usec_t ts = timeout == USEC_INFINITY ? USEC_INFINITY : usec_add(now(CLOCK_MONOTONIC), timeout);
/* ANCIENT-MOD: no pidfd (kernel < 5.3), poll with waitid(WNOHANG) to honour the timeout */
if (pidref->fd < 0 && ts != USEC_INFINITY)
for (;;) {
siginfo_t si = {};
r = RET_NERRNO(waitid(P_PID, pidref->pid, &si, WEXITED|WNOHANG));
if (r == -EINTR)
continue;
if (r < 0)
return r;
if (si.si_pid != 0) {
if (ret_si)
*ret_si = si;
return 0;
}
if (now(CLOCK_MONOTONIC) >= ts)
return -ETIMEDOUT;
(void) usleep_safe(10 * USEC_PER_MSEC);
}
/* Poll the pidfd before waitid() if either there's a finite timeout (so we can honor it) or /* Poll the pidfd before waitid() if either there's a finite timeout (so we can honor it) or
* we're on a fiber (so fd_wait_for_event() can suspend us instead of blocking the event loop * we're on a fiber (so fd_wait_for_event() can suspend us instead of blocking the event loop
* inside waitid()). Otherwise let waitid() block directly. The precondition above guarantees * inside waitid()). Otherwise let waitid() block directly. */
* pidref->fd >= 0 in both cases. */ bool poll_first = pidref->fd >= 0 && (ts != USEC_INFINITY || fiber_ops_is_set());
bool poll_first = ts != USEC_INFINITY || fiber_ops_is_set();
for (;;) { for (;;) {
if (poll_first) { if (poll_first) {
@@ -503,7 +522,7 @@ int pidref_wait_for_terminate_full(PidRef *pidref, usec_t timeout, siginfo_t *re
siginfo_t si = {}; siginfo_t si = {};
if (pidref->fd >= 0) if (pidref->fd >= 0)
r = RET_NERRNO(waitid(P_PIDFD, pidref->fd, &si, WEXITED)); r = RET_NERRNO(pidfd_waitid(pidref->fd, pidref->pid, &si, WEXITED));
else else
r = RET_NERRNO(waitid(P_PID, pidref->pid, &si, WEXITED)); r = RET_NERRNO(waitid(P_PID, pidref->pid, &si, WEXITED));
if (r >= 0) { if (r >= 0) {
+13 -1
View File
@@ -1419,13 +1419,25 @@ int socket_bind_to_ifname(int fd, const char *ifname) {
} }
int socket_bind_to_ifindex(int fd, int ifindex) { int socket_bind_to_ifindex(int fd, int ifindex) {
char ifname[IF_NAMESIZE];
int r;
assert(fd >= 0); assert(fd >= 0);
if (ifindex <= 0) if (ifindex <= 0)
/* Drop binding */ /* Drop binding */
return RET_NERRNO(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, NULL, 0)); return RET_NERRNO(setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, NULL, 0));
return setsockopt_int(fd, SOL_SOCKET, SO_BINDTOIFINDEX, ifindex); r = setsockopt_int(fd, SOL_SOCKET, SO_BINDTOIFINDEX, ifindex);
if (r != -ENOPROTOOPT)
return r;
/* ANCIENT-MOD: fall back to SO_BINDTODEVICE on kernels < 5.1 which didn't have SO_BINDTOIFINDEX */
r = format_ifname(ifindex, ifname);
if (r < 0)
return r;
return socket_bind_to_ifname(fd, ifname);
} }
int socket_autobind(int fd, char **ret_name) { int socket_autobind(int fd, char **ret_name) {
+133 -4
View File
@@ -11,14 +11,17 @@
#include "dirent-util.h" #include "dirent-util.h"
#include "errno-util.h" #include "errno-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h"
#include "filesystems.h" #include "filesystems.h"
#include "fs-util.h" #include "fs-util.h"
#include "hash-funcs.h" #include "hash-funcs.h"
#include "log.h" #include "log.h"
#include "mountpoint-util.h" #include "mountpoint-util.h"
#include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "siphash24.h" #include "siphash24.h"
#include "stat-util.h" #include "stat-util.h"
#include "stdio-util.h"
#include "string-util.h" #include "string-util.h"
#include "time-util.h" #include "time-util.h"
@@ -342,22 +345,40 @@ bool stat_is_empty(struct stat *st) {
} }
int null_or_empty_path_with_root(const char *fn, const char *root) { int null_or_empty_path_with_root(const char *fn, const char *root) {
_cleanup_free_ char *resolved = NULL;
_cleanup_close_ int fd = -EBADF;
struct stat st; struct stat st;
int r; int r;
assert(fn); assert(fn);
/* A symlink to /dev/null or an empty file? /* fn includes the root prefix. */
* When looking under root_dir, we can't expect /dev/ to be mounted,
* so let's see if the path is a (possibly dangling) symlink to /dev/null. */
if (path_equal(path_startswith(fn, root ?: "/"), "dev/null")) if (path_equal(path_startswith(fn, root ?: "/"), "dev/null"))
return true; return true;
r = chase_and_stat(fn, root, CHASE_PREFIX_ROOT, NULL, &st); if (empty_or_root(root)) {
if (stat(fn, &st) < 0)
return -errno;
return null_or_empty(&st);
}
/* An image below a root directory usually has no /dev/null, so a symlink to /dev/null dangles there.
* CHASE_NONEXISTENT resolves such a symlink without requiring the target to exist. */
r = chase(fn, root, CHASE_NONEXISTENT, &resolved, &fd);
if (r < 0) if (r < 0)
return r; return r;
if (path_equal(path_startswith(resolved, root), "dev/null"))
return true;
if (r == 0)
return -ENOENT;
if (fstat(fd, &st) < 0)
return -errno;
return null_or_empty(&st); return null_or_empty(&st);
} }
@@ -395,6 +416,102 @@ static const char* statx_attribute_to_name(uint64_t attr);
DEFINE_STATX_BITS_TO_STRING(statx_mask, unsigned, statx_mask_one_to_name, "0x%x"); DEFINE_STATX_BITS_TO_STRING(statx_mask, unsigned, statx_mask_one_to_name, "0x%x");
DEFINE_STATX_BITS_TO_STRING(statx_attributes, uint64_t, statx_attribute_to_name, "0x%" PRIx64); DEFINE_STATX_BITS_TO_STRING(statx_attributes, uint64_t, statx_attribute_to_name, "0x%" PRIx64);
/* ANCIENT-MOD: emulation of STATX_MNT_ID and STATX_ATTR_MOUNT_ROOT for kernels < 5.8 */
static int fd_fdinfo_mnt_id(int fd, uint64_t *ret) {
char path[STRLEN("/proc/self/fdinfo/") + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *p = NULL;
int r;
assert(fd >= 0);
assert(ret);
xsprintf(path, "/proc/self/fdinfo/%i", fd);
r = get_proc_field(path, "mnt_id", &p);
if (r == -ENOENT)
return proc_fd_enoent_errno();
if (r == -ENODATA)
return -EUNATCH;
if (r < 0)
return r;
return safe_atou64(p, ret);
}
static int fd_open_parent(int fd, const struct statx *sx) {
_cleanup_free_ char *p = NULL, *d = NULL;
int r;
if (FLAGS_SET(sx->stx_mask, STATX_TYPE) ? S_ISDIR(sx->stx_mode) : fd_verify_directory(fd) >= 0)
return RET_NERRNO(openat(fd, "..", O_PATH|O_DIRECTORY|O_CLOEXEC));
r = fd_get_path(fd, &p);
if (r < 0)
return r;
r = path_extract_directory(p, &d);
if (r < 0)
return r;
return RET_NERRNO(open(d, O_PATH|O_DIRECTORY|O_CLOEXEC));
}
static int xstatx_emulate(
int fd,
const char *path,
int statx_flags,
bool want_mnt_id,
bool want_mount_root,
struct statx *sx) {
_cleanup_close_ int target_fd = -EBADF, parent_fd = -EBADF;
uint64_t mnt_id, parent_mnt_id;
int r;
assert(sx);
if (isempty(path) && fd >= 0)
target_fd = RET_NERRNO(fcntl(fd, F_DUPFD_CLOEXEC, 3));
else
target_fd = RET_NERRNO(openat(fd, isempty(path) ? "." : path,
O_PATH|O_CLOEXEC|(FLAGS_SET(statx_flags, AT_SYMLINK_NOFOLLOW) ? O_NOFOLLOW : 0)));
if (target_fd < 0)
return target_fd;
r = fd_fdinfo_mnt_id(target_fd, &mnt_id);
if (r < 0)
return r;
if (want_mnt_id) {
sx->stx_mnt_id = mnt_id;
sx->stx_mask |= STATX_MNT_ID;
}
if (!want_mount_root)
return 0;
bool is_root = false;
parent_fd = fd_open_parent(target_fd, sx);
if (parent_fd < 0)
log_debug_errno(parent_fd, "Failed to open parent to determine mount root, assuming not a mount root: %m");
else {
struct stat a, b;
r = fd_fdinfo_mnt_id(parent_fd, &parent_mnt_id);
if (r < 0)
return r;
if (mnt_id != parent_mnt_id)
is_root = true;
else if (fstat(target_fd, &a) >= 0 && fstat(parent_fd, &b) >= 0)
is_root = stat_inode_same(&a, &b);
}
SET_FLAG(sx->stx_attributes, STATX_ATTR_MOUNT_ROOT, is_root);
sx->stx_attributes_mask |= STATX_ATTR_MOUNT_ROOT;
return 0;
}
int xstatx_full(int fd, int xstatx_full(int fd,
const char *path, const char *path,
int statx_flags, int statx_flags,
@@ -439,6 +556,18 @@ int xstatx_full(int fd,
&sx) < 0) &sx) < 0)
return negative_errno(); return negative_errno();
bool want_mnt_id =
(FLAGS_SET(xstatx_flags, XSTATX_MNT_ID_BEST) && !(sx.stx_mask & (STATX_MNT_ID|STATX_MNT_ID_UNIQUE))) ||
(FLAGS_SET(request_mask, STATX_MNT_ID) && !FLAGS_SET(sx.stx_mask, STATX_MNT_ID));
bool want_mount_root =
FLAGS_SET(mandatory_attributes, STATX_ATTR_MOUNT_ROOT) &&
!FLAGS_SET(sx.stx_attributes_mask, STATX_ATTR_MOUNT_ROOT);
if (want_mnt_id || want_mount_root) {
r = xstatx_emulate(fd, path, statx_flags, want_mnt_id, want_mount_root, &sx);
if (r < 0)
log_debug_errno(r, "Failed to emulate statx() mount fields, ignoring: %m");
}
if (FLAGS_SET(xstatx_flags, XSTATX_MNT_ID_BEST) && if (FLAGS_SET(xstatx_flags, XSTATX_MNT_ID_BEST) &&
!(sx.stx_mask & (STATX_MNT_ID|STATX_MNT_ID_UNIQUE))) !(sx.stx_mask & (STATX_MNT_ID|STATX_MNT_ID_UNIQUE)))
return log_debug_errno(SYNTHETIC_ERRNO(EUNATCH), "statx() did not return either STATX_MNT_ID or STATX_MNT_ID_UNIQUE."); return log_debug_errno(SYNTHETIC_ERRNO(EUNATCH), "statx() did not return either STATX_MNT_ID or STATX_MNT_ID_UNIQUE.");
+6 -4
View File
@@ -414,8 +414,10 @@ char* ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
bool has_ansi_seq = string_has_ansi_sequence(s, old_length); bool has_ansi_seq = string_has_ansi_sequence(s, old_length);
/* If no multibyte characters or ANSI sequences, use ascii_ellipsize_mem for speed */ /* If no multibyte characters or ANSI sequences, use ascii_ellipsize_mem for speed. It equates
if (!has_ansi_seq && ascii_is_valid_n(s, old_length)) * bytes with character cells, which holds for ASCII except for the tab, which
* unichar_console_width() counts as 8 cells. */
if (!has_ansi_seq && ascii_is_valid_n(s, old_length) && !memchr(s, '\t', old_length))
return ascii_ellipsize_mem(s, old_length, new_length, percent); return ascii_ellipsize_mem(s, old_length, new_length, percent);
x = (new_length - 1) * percent / 100; x = (new_length - 1) * percent / 100;
@@ -436,7 +438,7 @@ char* ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
char32_t c; char32_t c;
assert_se(utf8_encoded_to_unichar(i, &c) == r); assert_se(utf8_encoded_to_unichar(i, &c) == r);
int w = unichar_iswide(c) ? 2 : 1; int w = unichar_console_width(c);
if (k + w > x) if (k + w > x)
break; break;
@@ -467,7 +469,7 @@ char* ellipsize_mem(const char *s, size_t old_length, size_t new_length, unsigne
if (!tt) if (!tt)
return NULL; return NULL;
w = unichar_iswide(c) ? 2 : 1; w = unichar_console_width(c);
if (k + w > new_length) if (k + w > new_length)
break; break;
+10 -8
View File
@@ -8,6 +8,7 @@
#include "escape.h" #include "escape.h"
#include "extract-word.h" #include "extract-word.h"
#include "fileio.h" #include "fileio.h"
#include "gunicode.h"
#include "hashmap.h" #include "hashmap.h"
#include "log.h" #include "log.h"
#include "memory-util.h" #include "memory-util.h"
@@ -1281,13 +1282,14 @@ int strv_rebreak_lines(char **l, size_t width, char ***ret) {
in_prefix = false; in_prefix = false;
} }
char32_t c; /* Measure with the same helper utf8_console_width() uses. Our callers mix the
int n = utf8_encoded_to_unichar(p, &c); * two: sd-varlink-idl.c and verbs.c size their indent with utf8_console_width()
if (n < 0) * and then break the body here, so if we accepted and measured what that one
return log_debug_errno(n, "Line to break contains invalid UTF-8, refusing: %m"); * refuses we'd be computing a single width from two ideas of what valid UTF-8
* is. */
int cw = unichar_console_width(c); int cw = utf8_char_console_width(p);
assert(cw >= 0); if (cw < 0)
return log_debug_errno(cw, "Line to break contains invalid UTF-8, refusing: %m");
w += cw; w += cw;
@@ -1312,7 +1314,7 @@ int strv_rebreak_lines(char **l, size_t width, char ***ret) {
continue; continue;
} }
p += n; p = utf8_next_char(p);
} }
/* Process rest of the line, except if all that's left after the last newline we already /* Process rest of the line, except if all that's left after the last newline we already
+24 -9
View File
@@ -1046,7 +1046,7 @@ int lock_dev_console(void) {
return TAKE_FD(fd); return TAKE_FD(fd);
} }
int make_console_stdio(void) { int make_console_stdio(bool switch_to_text) {
int fd, r; int fd, r;
/* Make /dev/console the controlling terminal and stdin/stdout/stderr, if we can. If we can't use /* Make /dev/console the controlling terminal and stdin/stdout/stderr, if we can. If we can't use
@@ -1062,7 +1062,7 @@ int make_console_stdio(void) {
return log_error_errno(r, "Failed to make /dev/null stdin/stdout/stderr: %m"); return log_error_errno(r, "Failed to make /dev/null stdin/stdout/stderr: %m");
} else { } else {
reset_dev_console_fd(fd, /* switch_to_text= */ true); reset_dev_console_fd(fd, switch_to_text);
r = rearrange_stdio(fd, fd, fd); /* This invalidates 'fd' both on success and on failure. */ r = rearrange_stdio(fd, fd, fd); /* This invalidates 'fd' both on success and on failure. */
if (r < 0) if (r < 0)
@@ -2681,17 +2681,32 @@ int terminal_get_size(
return r; return r;
} }
static int fd_is_vc(int fd) {
_cleanup_free_ char *name = NULL;
int r;
assert(fd >= 0);
r = getttyname_harder(fd, &name);
if (r < 0)
return r;
return tty_is_vc_resolve(name);
}
int terminal_fix_size(int input_fd, int output_fd) { int terminal_fix_size(int input_fd, int output_fd) {
unsigned rows, columns; unsigned rows, columns;
int r; int r;
/* Tries to update the current terminal dimensions to the ones reported via ANSI sequences. /* Don't ask a virtual console at all. There is no intermediary here that could be wrong about the
* * dimensions: the kernel renders the screen itself, so its winsize is authoritative. */
* Why bother with this? The ioctl() information is often incorrect on serial terminals (since r = fd_is_vc(input_fd);
* there's no handshake or protocol to determine the right dimensions in RS232), but since the ANSI if (r < 0)
* sequences are interpreted by the final terminal instead of an intermediary tty driver they should log_debug_errno(r, "Failed to determine whether terminal is a virtual console, assuming it is not: %m");
* be more accurate. else if (r > 0) {
*/ log_debug("Not querying dimensions of a virtual console, kernel dimensions are authoritative.");
return 0;
}
struct winsize ws = {}; struct winsize ws = {};
if (ioctl(output_fd, TIOCGWINSZ, &ws) < 0) if (ioctl(output_fd, TIOCGWINSZ, &ws) < 0)
+1 -1
View File
@@ -112,7 +112,7 @@ int vtnr_from_tty(const char *tty);
void reset_dev_console_fd(int fd, bool switch_to_text); void reset_dev_console_fd(int fd, bool switch_to_text);
int lock_dev_console(void); int lock_dev_console(void);
int make_console_stdio(void); int make_console_stdio(bool switch_to_text);
int getenv_columns(void); int getenv_columns(void);
int fd_columns(int fd); int fd_columns(int fd);
+7 -1
View File
@@ -181,10 +181,16 @@ int utf8_char_console_width(const char *str) {
assert(str); assert(str);
r = utf8_encoded_to_unichar(str, &c); /* Validate the same way utf8_is_valid() does. utf8_encoded_to_unichar() on its own accepts
* overlong encodings, surrogates, noncharacters and the obsolete 5 and 6 byte forms, which would
* make our idea of how wide a string is disagree with our idea of whether it is valid UTF-8 in
* the first place. */
r = utf8_encoded_valid_unichar(str, SIZE_MAX);
if (r < 0) if (r < 0)
return r; return r;
assert_se(utf8_encoded_to_unichar(str, &c) == r);
return unichar_console_width(c); return unichar_console_width(c);
} }
+1 -1
View File
@@ -295,7 +295,7 @@ int xsetxattr_full(
assert(fd >= 0 || fd == AT_FDCWD); assert(fd >= 0 || fd == AT_FDCWD);
assert((at_flags & ~(AT_SYMLINK_FOLLOW|AT_EMPTY_PATH)) == 0); assert((at_flags & ~(AT_SYMLINK_FOLLOW|AT_EMPTY_PATH)) == 0);
assert(name); assert(name);
assert(value); assert(value || size == 0);
if (size == SIZE_MAX) if (size == SIZE_MAX)
size = strlen(value); size = strlen(value);
+2
View File
@@ -219,6 +219,8 @@ static int run(int argc, char *argv[]) {
else else
log_debug("Flushed all binfmt_misc rules."); log_debug("Flushed all binfmt_misc rules.");
r = 0;
STRV_FOREACH(f, files) STRV_FOREACH(f, files)
RET_GATHER(r, apply_file(*f, true)); RET_GATHER(r, apply_file(*f, true));
} }
+33
View File
@@ -3,6 +3,7 @@
#include <unistd.h> #include <unistd.h>
#include "sd-json.h" #include "sd-json.h"
#include "sd-varlink.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "build.h" #include "build.h"
@@ -20,6 +21,7 @@
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
#include "sync-util.h" #include "sync-util.h"
#include "varlink-util.h"
#include "verbs.h" #include "verbs.h"
#include "virt.h" #include "virt.h"
@@ -443,6 +445,8 @@ VERB_FULL(verb_set, "indeterminate", NULL, VERB_ANY, 1, 0, STATUS_INDETERMINATE,
"Undo any marking as good or bad"); "Undo any marking as good or bad");
static int verb_set(int argc, char *argv[], uintptr_t data, void *userdata) { static int verb_set(int argc, char *argv[], uintptr_t data, void *userdata) {
_cleanup_free_ char *path = NULL, *prefix = NULL, *suffix = NULL, *good = NULL, *bad = NULL; _cleanup_free_ char *path = NULL, *prefix = NULL, *suffix = NULL, *good = NULL, *bad = NULL;
_cleanup_(sd_varlink_unrefp) sd_varlink *link = NULL;
sd_json_variant *reply = NULL;
const char *target = NULL, *source1 = NULL, *source2 = NULL; /* avoid false maybe-uninitialized warning */ const char *target = NULL, *source1 = NULL, *source2 = NULL; /* avoid false maybe-uninitialized warning */
uint64_t left, done; uint64_t left, done;
Status status = data; Status status = data;
@@ -454,6 +458,35 @@ static int verb_set(int argc, char *argv[], uintptr_t data, void *userdata) {
if (r < 0) if (r < 0)
return r; return r;
/* kexec doesn't go through the EFI loaders, so we shouldn't try to mark an image as good/bad.
* E.g.: booting the kernel+initrd might work, but the EFI stub might not, and we wouldn't notice */
r = sd_varlink_connect_address(&link, "/run/systemd/io.systemd.Manager");
if (r < 0)
return log_error_errno(r, "Failed to connect to service manager: %m");
r = varlink_call_and_log(link, "io.systemd.Manager.Describe", /* parameters= */ NULL, &reply);
if (r < 0)
return r;
static const sd_json_dispatch_field dispatch_table[] = {
{ "KExecCount", SD_JSON_VARIANT_UNSIGNED, sd_json_dispatch_uint64, 0, 0 },
{},
};
uint64_t kexec_count = 0;
r = sd_json_dispatch(
sd_json_variant_by_key(reply, "runtime"),
dispatch_table,
SD_JSON_LOG|SD_JSON_ALLOW_EXTENSIONS,
&kexec_count);
if (r < 0)
return r;
if (kexec_count > 0) {
log_info("System was booted via kexec, skipping boot entry marking.");
return 0;
}
r = acquire_boot_count_path(&path, &prefix, &left, &done, &suffix); r = acquire_boot_count_path(&path, &prefix, &left, &done, &suffix);
if (r == -EUNATCH) /* acquire_boot_count_path() won't log on its own for this specific error */ if (r == -EUNATCH) /* acquire_boot_count_path() won't log on its own for this specific error */
return log_error_errno(r, "Not booted with boot counting in effect."); return log_error_errno(r, "Not booted with boot counting in effect.");
+5 -2
View File
@@ -2493,14 +2493,17 @@ static void boot_entry_add_type2(
/* If the filename had no tries suffixes then the id won't be set by the above call, do it now */ /* If the filename had no tries suffixes then the id won't be set by the above call, do it now */
if (!entry->id) if (!entry->id)
entry->id = strtolower16(xstrdup16(filename)); entry->id = xstrdup16(filename);
/* Patterns are case folded before matching, hence IDs must be too. */
strtolower16(entry->id);
/* Ensure the secondary profiles IDs also have the tries suffix stripped, to match the primary */ /* Ensure the secondary profiles IDs also have the tries suffix stripped, to match the primary */
if (profile > 0) { if (profile > 0) {
entry->id_without_profile = TAKE_PTR(entry->id); entry->id_without_profile = TAKE_PTR(entry->id);
if (profile_id) if (profile_id)
entry->id = xasprintf("%ls@%ls", entry->id_without_profile, profile_id); entry->id = strtolower16(xasprintf("%ls@%ls", entry->id_without_profile, profile_id));
else else
entry->id = xasprintf("%ls@%u", entry->id_without_profile, profile); entry->id = xasprintf("%ls@%u", entry->id_without_profile, profile);
+1 -1
View File
@@ -266,7 +266,7 @@ if cc.get_id() == 'clang'
endif endif
efi_arch_c_args = { efi_arch_c_args = {
'aarch64' : ['-mgeneral-regs-only'], 'aarch64' : ['-mgeneral-regs-only', '-ffixed-x18'],
'arm' : ['-mgeneral-regs-only'], 'arm' : ['-mgeneral-regs-only'],
# Until -mgeneral-regs-only is supported in LoongArch, use the following option instead: # Until -mgeneral-regs-only is supported in LoongArch, use the following option instead:
'loongarch64' : ['-mno-lsx', '-mno-lasx'], 'loongarch64' : ['-mno-lsx', '-mno-lasx'],

Some files were not shown because too many files have changed in this diff Show More