Commit Graph
1464 Commits
Author SHA1 Message Date
Lennart Poettering 0bfed33959 tree-wide: close-on-exec by default (#43692)
In any modern codebase `O_CLOEXEC` should be the default and file
descriptor inheritance must be explicitly enabled. Flip the switch and
port everyone to our internal open helpers as well.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-11-02 15:31:57 +01:00
Luca Boccassi 45b53d7fbf boot: add support for installing fwupd capsules
fwupd prepares capsules in the ESP and corresponding non-volatile
variables that describe them. It currently ships an EFI binary that
parses and applies them, but the intention is to deprecate it and
move the functionality into bootloaders. A new volatile variable
can be set by a bootloader that supports this workflow, and if
fwupd finds it, it will no longer use its own EFI binary.

Port the implementation from https://github.com/fwupd/fwupd-efi/blob/main/efi/fwupdate.c
and adapt it. The high level flow is defined at
https://github.com/fwupd/fwupd-efi/blob/main/SECURITY.md

Fixes https://github.com/systemd/systemd/issues/36643
2026-11-02 11:07:30 +01:00
Christian Brauner 88e3711029 docs: document that our open helpers set O_CLOEXEC themselves
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-11-02 09:21:10 +01:00
Luca Boccassi c5db3b2276 core: add FDSTOREWIPE notify message to wipe FD store
Add a new parameter to the sd_notify FD store interface that allows
units to easily wipe the content of their own store, without having
to call into D-Bus.
2026-10-31 10:20:30 +00:00
Luca Boccassi f54edff8c3 core: propagate CleanUnit('fdstore') to upper managers
With FileDescriptorStorePreserve=yes we propagate the FD Stores of a
user session to the system manager, but running CleanUnit was not
propagated so the FD Stores of a cleaned unit remained in the upper
store and were restored.

Follow-up for 5608575e01
2026-10-31 10:20:30 +00:00
Daan De Meyer 12d8bb84b1 mkosi: share packaging pins with other build tools
The packaging references are part of mkosi's configuration, so tine can't
build a checkout with the same pinned spec. Let's share the pins in one
JSON file keyed by distro and keep mkosi, the packaging updater and
Packit using it.
2026-10-30 13:20:54 +01:00
Lennart Poettering f1d45e3d14 vmspawn: use initrd cpio for credentials on TDX direct boot (#44484) 2026-10-30 12:21:48 +01:00
Lennart Poettering 885e4b4d67 man,docs: document EFI variable erasing on factory reset
Document the new LoaderFactoryResetVariables EFI variable, and the new
systemd-efivars-clear.service.
2026-10-29 19:53:35 +01:00
Paul Meyer 224a37a47b boot: set LoaderPcrSMBIOS only if all structures were measured
So far the variable was set as soon as one of the SMBIOS structures
(types 1, 2 and 11) was measured, and a later failure on another only
logged.The original intent was to prevent sd-stub from measuring these
things a second time after sd-boot already did.

This PR adds a second consumer: in a confidential VM, PID 1 takes the
variable as confirmation that the SMBIOS OEM strings are covered by
PCR 1 before it imports credentials from them. Make the loader provide
that guarantee and leave the variable unset if any structure could not
be measured, which also matches how the documentation already describes
it.

The effect on the existing consumer is limited to boots with a
measurement failure: when sd-boot fails to measure some of the structs
and then chainloads sd-stub, sd-stub measures the structs sd-boot was
able to measure a second time. Previously it would have left the
incomplete measurement as is. In that situation PCR 1 already didn't
match the expected value before (events missing), and after this change
it still won't (additional events), so anything bound to it, such as a
pcrlock policy, does not match either way.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
2026-10-29 13:02:45 +01:00
Adrian Vovk b383b17eb2 CONTRIBUTING: Add template for LLM violation (#44475)
The policy requires a warning before a ban, so this throws in two
messages that we can copy + paste so we don't have to draft a bespoke
warning each time someone violates the rule
2026-10-28 17:27:33 +01:00
Luca Boccassi feb1e5fbae ci: switch deb packaging repo to github
salsa is very flaky and CI jobs constantly fail when pulling from it.
Switch to github repo in our org so that it is more reliable
(if it's down, the CI jobs are down as well by definition, so no
combinatorial probability of outages
2026-10-28 11:04:15 +00:00
Jonas Burgdorf 6284bbe479 network: make addresses limits configurable via environment
This introduces environment variables $SYSTEMD_NETWORK_MAX_ADDRESSES_PER_LINK
and $SYSTEMD_NETWORK_STATIC_ADDRESSES_PER_NETWORK to make these resource
limits adjustable via the environment.
2026-10-28 17:10:44 +09:00
Adrian Vovk bb9e9571c3 CONTRIBUTING: Add template for LLM violation
The policy requires a warning before a ban, so this throws in two
messages that we can copy + paste so we don't have to draft a bespoke
warning each time someone violates the rule
2026-10-27 16:58:05 -04:00
Christian Brauner 3707468837 rust: pass the command line tables around as sections
dispatch_verb!(), command_print_help_name!(), command_print_verb_help!()
and introspect_cli!() each declare the bounds the linker defines for
the SYSTEMD_VERBS and SYSTEMD_OPTIONS sections and hand them to an
unsafe backend as four raw pointers. foreach_option!() does the same
and needs OptionParser::__parser() only so that it can evaluate its
argument outside of the unsafe block.

Instead, wrap the bounds in a Section<T> that only __verbs_section!()
and __options_section!() create. Creating it is the unsafe part, so the
backends become safe functions and each table macro is a single call.
foreach_option!() calls a safe OptionParser::__next() now and
__parser() is gone.

The verbs get the userdata as it is though. So __dispatch_verb() stays
unsafe and dispatch_verb!() expands to the call directly. IOW, the
caller vouches for the userdata in an unsafe block of its own instead
of the macro hiding that in its unsafe block. clippy's
not_unsafe_ptr_arg_deref caught this once the bounds were gone.

The new code takes the address of the bounds with &raw const,
addr_of!() is soft-deprecated.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-27 12:25:05 +01:00
DavidVB10 db16b6c8ec docs: document control codepoints correctly
The previous documentation did not correctly exclude 127 (DEL) and the C1 control character
range 128-159 from the control codepoints.

However, the function unichar_is_control() defined on src/basic/utf8.c includes the range
0x7F (i.e. 127) to 0x9F (i.e. 159) as control codepoints. This commit explicitly documents the
127-159 range as control.

Fixes #44202.
2026-10-27 16:00:46 +09:00
Daan De Meyer e472d3ea3d Only require verity signatures if the host's image policy requires them (#44234)
Today, whether dissect-image insists on a valid dm-verity signature
often
depends on the image instead of on the host. With the default policies,
an
image without a signature mounts fine. The same image fails to mount if
it
contains a malformed signature partition or a signature that userspace
validation can't parse. If a root hash is configured, it also fails if
it
has no signature partition at all.

The image is input we don't trust. Whoever builds it controls whether it
contains a signature and what the signature contains. Checks that depend
on
the image contents give no protection, because anyone who wants to get
past
them can remove the signature. They only break images that work fine as
plain
Verity images. Whether a signature is required has to come from the
host's
image policy. A policy that allows "signed" but not "verity", such as
`RootImagePolicy=root=signed`, requires a valid signature. With the
default
policies, the signature is optional.

Making that the rule exposed two ways to bypass a policy that requires a
signature: reusing a shared Verity device that was set up without a
validated
signature, and mounting a partition directly when no root hash is known.
The
PR fixes those first, so every commit keeps signed-only policies intact.

Behavior changes worth calling out:

- With the default policies, images whose signature is missing,
malformed or
  can't be validated are set up with Verity alone.
- Under a policy that requires a signature, a shared Verity device is
only
reused if the kernel validated a signature for it. If we have a
signature
and the policy allows "signed", we set up our own device instead of
reusing
one without a validated signature. A device with a validated signature
is
  reused even if the caller has no signature.
- A root or usr partition whose policy allows neither "unprotected" nor
  "unused" is refused if we can't set up Verity for it, instead of being
mounted directly. As a result, a DDI with Verity for both the root and
the
usr partition is refused under a policy that requires Verity for usr,
such
  as systemd-mountfsd's policy for untrusted images.

The measurement fix and the mountfsd device sharing fix from earlier
versions
of this PR were merged in #44386 and #44387. The veritysetup and
gpt-auto
changes, the mountfsd polkit changes and the portable changes will
follow as
separate PRs on top of this one.
2026-10-26 17:35:56 +01:00
Christian Brauner 161807edb1 rust: wrap the libsystemd-shared helpers systemd-keyring-setup needs (#44325)
Lennart asked in #44114 to split the preparatory stuff out so it can
be merged in smaller PRs. So this is a stack of five, each based on
the one before it and each showing only its own commits:

1. #44323, the C helpers (merged)
2. #44324, support for programs written in Rust (merged)
3. #44420, bindings.h lists only the headers Rust code uses (merged)
4. #44325, the systemd_shared wrappers systemd-keyring-setup needs
5. #44114, systemd-keyring-setup itself

This one is 4. Each wrapper commit adds the headers it needs to
bindings.h.

This adds the systemd_shared wrappers systemd-keyring-setup is written
against, so #44114 is left with just the program.

The wrappers follow the pattern of the crate: thin, fallible, with the
C names and anchored at file descriptors. They cover

- the file and directory helpers: the chase_and_*at() family,
  read_full_file_full() into the buffer C allocated, which is erased on
  drop when it was read with READ_FULL_FILE_SECURE, the linkable
  temporary files of tmpfile-util.h, readdir_all(), the credentials
  directory resolved below a root and loop_write() and fchmod()
- the keyring-util helpers
- the VOA lookup, with ConfFiles owning the array a lookup returns
- the X.509 helpers of crypto-util behind HAVE_OPENSSL, with X509
  owning the certificate and giving access to the extension and key
  usage flags, the subject key identifier, the serial number and the
  DER and PEM encodings
- format-table
- module-util, with the libkmod context freed on drop
- .note.dlopen ELF notes. elf_note_dlopen!() writes the same note
  SD_ELF_NOTE_DLOPEN() writes, so a Rust program declares its dlopen()
  dependencies the way the C programs do and systemd-analyze
  dlopen-metadata sees them.

Flag combinations the C helpers assert on fail with -EINVAL instead.
test-rust-shared covers all of it.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-26 14:30:43 +01:00
Daan De Meyer a726e292c1 man: document when verity signatures are required
The man pages don't say what happens when an image policy allows
"verity" as well as "signed" and the signature can't be validated.
systemd.exec(5) even claims that RootHashSignature= only opens the
volume if the kernel validates the signature, which isn't true with the
default policy.

Let's document that only a policy that allows "signed" without "verity"
requires a valid signature, in systemd.image-policy(7),
systemd.exec(5), systemd-dissect(1) and for
$SYSTEMD_DISSECT_VERITY_SIGNATURE, and add a NEWS entry for the changed
behavior.
2026-10-26 14:06:54 +01:00
Daan De Meyer 527273f254 mountfsd: restrict unprivileged Verity device reuse (#44387) 2026-10-26 13:19:43 +01:00
Christian Brauner 498ada9e00 rust: emit .note.dlopen ELF notes
Packaging tools read the dlopen() dependencies of a program from its
.note.dlopen ELF notes. elf_note_dlopen!() writes the same note
SD_ELF_NOTE_DLOPEN() writes into a static in that section. LLVM makes
it an SHT_NOTE section because of its name. The static is referenced
from the function that uses it so --gc-sections keeps the note for as
long as the function, just like the anchored C variant does.
libcrypto_note!() and libkmod_note!() are LIBCRYPTO_NOTE() and
LIBKMOD_NOTE().

SD_ELF_NOTE_DLOPEN_TYPE is spelled with UINT32_C() which bindgen can't
evaluate so it gets a const helper.

HACKING.md asks programs to declare their dlopen() dependencies with
these macros.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-26 09:36:01 +01:00
Daan De Meyer 55f7d28c36 mountfsd: restrict unprivileged Verity device reuse
Unprivileged mountfsd clients can select the root hash of a shared Verity
device and read its contents without opening the original image.

Let's require the same backing file when non-root clients reuse Verity
devices through mountfsd. Privileged clients and other callers keep
sharing by root hash without needing loop device metadata.
2026-10-25 19:46:21 +01:00
Christian Brauner 87bdd67824 rust: bind only the headers Rust code uses
So far bindings.h listed every header of src/basic/, src/shared/ and
src/systemd/ and the crate bound everything libsystemd-shared exports.
That buys nothing. Nothing of it ends up in a binary and no Rust code
reaches it. It does cost though: the generated crate is 2.7 MB and the
rlib 15 MB, every regeneration takes 5 s, rust-analyzer chews on
all of it, and whenever bindgen chokes on a header nobody uses the
Rust build breaks. Two of the four bindgen workarounds in meson.build
exist only because of that, the packed journal objects and the PE
header.

Instead, list the headers the Rust code uses, 18 right now, and let
every wrapper that needs another one add it. That's how the kernel does
it with bindings_helper.h and QEMU with wrapper.h. The libc and kernel
constants keep arriving by family through the allowlist, bindings.h
lists their headers so that doesn't hang on what the tree's headers
happen to include. The generated crate shrinks to 260 KB and
regenerating it takes a second. The binaries don't change.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-25 17:27:54 +01:00
Christian Brauner 8f9c69af31 rust: add an allocator that erases memory before freeing it
C code keeps secrets in buffers that it frees with erase_and_free().
That's a convention every caller has to remember. With the allocator
being part of the type Rust code can make it a guarantee instead.

Add Erasing which allocates like Malloc but frees memory with
erase_and_free(), which erases it first. It never uses realloc() as
that may leave the old contents behind in the memory it frees. Growing
allocates anew, copies and erases the old memory instead. So a buffer
holding a key or a passphrase is simply a Vec<u8, Erasing>.

Note that elements a Vec drops early via pop() or truncate() stay in
its memory until it is freed.

HACKING.md and CODING_STYLE.md point secrets at it.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-23 16:34:47 +02:00
Christian Brauner 66412c31bb docs: document writing programs in Rust
HACKING.md describes how a program is declared and written with the
command line framework of the C programs, what the toolchain
requirements and the per-distribution packages are, what a Rust program
costs and what it may not do (std, external crates), how the build
treats Rust code (lint set, overflow checks, panic=abort, remapped
paths, no CET markers) and where the tests, clippy, rustdoc and the
rust-analyzer project file are.

CODING_STYLE.md gets the rules for Rust code:

- rustfmt and the enforced lint set
- define_main!()
- the systemd_shared crate as the only way to talk to the rest of
  systemd
- names mirroring the C names
- SAFETY comments and Safety sections
- BorrowedFd for file descriptors
- no_std
- the error handling conventions
- #[expect] over #[allow]
- allocation failure never panicking or aborting, like in the kernel
- no pointless copies of strings

ARCHITECTURE.md explains where the Rust code lives. README lists rustc
and bindgen among the optional build dependencies, and NEWS tells
packagers that builds with --auto-features=enabled now need them or
-Drust=disabled.

CODING_STYLE.md also spells out the rules the systemd maintainers
agreed on for Rust: it is only used for new leaf components and
existing C code isn't ported, it's built with meson and without cargo,
only the core, alloc and libc crates are permitted, and Rust code only
talks to the rest of systemd through C linkage.

Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
2026-10-23 16:34:47 +02:00
Martin Pitt 1592d554e5 condition: make ConditionCredential= also search the credential stores
Credentials can reach a system through the credential stores. E.g.
`systemd-imds --import` writes cloud provided credentials to
`/run/credstore/` in the initrd. `ImportCredential=` already finds them
there, but `ConditionCredential=` and `AssertCredential=` only checked
the credentials passed into the service manager itself. Hence, a
credential in the store could configure a service, but not decide
whether a unit runs.

Make the credential condition search the same credential store
directories as `ImportCredential=`. Only the existence of a credential
is checked, encrypted ones are not decrypted.

This is a behaviour change, see NEWS. As before, non-root callers which
can't access a credential store treat these as absent, otherwise this
would break running e.g. `systemd-analyze` or `sysetmd-sysupdate` as
user.

Signed-off-by: Martin Pitt <martin@amutable.com>
2026-10-20 06:55:47 +02:00
Paul Meyer a923ab5ed1 sd-varlink-idl: add SD_VARLINK_EXPERIMENTAL marker (#44287)
Allow marking Varlink interfaces, methods, errors, types, fields and
  enum values as experimental, for documentation and discoverability.
  Calls are not refused.

  - One SD_VARLINK_EXPERIMENTAL flag works for interface, symbol and
    field flags; _FULL variants of the definition macros take flags.
    Interface and symbol flags are now validated, and the internal
    _SD_VARLINK_*_FLAGS_MAX are replaced by _SD_VARLINK_*_FLAGS_ALL.
  - The IDL output shows experimental items with a "# [Experimental]"
comment line, and sd_varlink_idl_parse() turns it back into the flag,
    so the information survives GetInterfaceDescription.
- varlink_idl_consistent() refuses non-experimental fields referring to
    experimental types, non-nullable experimental fields in
    non-experimental symbols, and experimental values in
    non-experimental enums. These rules are deliberately strict, so that
    they can be relaxed later without breaking anything.
  - varlinkctl highlights experimental methods in list-methods and shows
    a notice when calling one (only when on a terminal).
  - docs/PORTABILITY_AND_STABILITY.md now excludes experimental parts of
    Varlink interfaces from the stability promise.
- Fixes resolution of named types within anonymous types in the parser,
    which the new checks ran into.
  - io.systemd.PCRLock is marked experimental as a first user; other
    experimental components will follow once the design is settled.

  Open questions:
  - Should experimental values in non-experimental enums be permitted in
    some cases, e.g. for enums only used as input?
- Should experimental errors be allowed in non-experimental interfaces?
    The IDL does not link errors to methods, so this is documentation
    only.
2026-10-19 15:27:04 +02:00
Paul Meyer 931a744b6c NEWS, docs: document SD_VARLINK_EXPERIMENTAL
Signed-off-by: Paul Meyer <katexochen0@gmail.com>
2026-10-19 11:28:33 +02:00
Lennart Poettering e276965280 dissect-image: enforce validatefs xattrs when mounting partitions
So far the constraints a file system declares about itself via the
user.validatefs.* xattrs were only checked by systemd-validatefs@.service
for file systems mounted via .mount units. Let's validate them also when
mounting partitions of DDIs, i.e. for systemd-dissect, systemd-nspawn,
portabled, sysext, RootImage= and mountfsd.

Any constraint that is set must be fulfilled in full: if a file system
declares GPT label or type constraints but isn't placed on a GPT
partition (for example because it is a bare file system image, or on an
MBR partition table) mounting is refused. If the partition is Verity
protected, the constraints must be fulfilled by the Verity hash
partition too, which matches the behaviour of systemd-validatefs.

Validation is done when the superblock is created, i.e. on the mountfsd
side if mountfsd is used. It can be turned off via
$SYSTEMD_DISSECT_VALIDATEFS=0. If validation fails, mounting returns
-EHWPOISON.
2026-10-17 17:44:29 +02:00
Lennart Poettering db34d7f479 report: add a simple geoip source 2026-10-17 07:52:31 +02:00
Daan De Meyer 08190bcf15 nss-systemd: add $SYSTEMD_NSS_SERVER_SIDE_NSS (#44086)
nss-systemd always passes USERDB_EXCLUDE_NSS to userdb. That flag skips
the io.systemd.NameServiceSwitch and io.systemd.Multiplexer services. A
sandbox can bind mount the host's userdb sockets into
/run/systemd/userdb/,
but nss-systemd in that sandbox still cannot resolve the host's regular
users and groups.

Add $SYSTEMD_NSS_SERVER_SIDE_NSS. If it is set, nss-systemd queries the
server-side NSS services too. Client-side NSS stays off, because
nss-systemd itself runs as a glibc NSS module.
2026-10-16 14:46:06 +02:00
Lennart Poettering cc76554de0 docs: two follow-ups for NV Index registry commit
As per review comments on https://github.com/systemd/systemd/pull/33394

Follow-up for: 6e12c598d3
2026-10-16 09:16:07 +02:00
Daan De Meyer 7741b0012e nss-systemd: add $SYSTEMD_NSS_SERVER_SIDE_NSS
nss-systemd always passes USERDB_EXCLUDE_NSS to userdb. That flag skips
the io.systemd.NameServiceSwitch and io.systemd.Multiplexer services. A
sandbox can bind mount the host's userdb sockets into /run/systemd/userdb/,
but nss-systemd in that sandbox still cannot resolve the host's regular
users and groups.

Add $SYSTEMD_NSS_SERVER_SIDE_NSS. If it is set, nss-systemd queries the
server-side NSS services too. Client-side NSS stays off, because
nss-systemd itself runs as a glibc NSS module.
2026-10-15 09:36:02 +02:00
Lennart Poettering 6e12c598d3 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!
2026-10-15 08:53:27 +02:00
Achill Gilgenast 0f655ffc7b 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
2026-10-15 02:35:29 +09:00
Ivan Kruglov 1c754bf06e docs: clarify Varlink input and output policy 2026-10-14 15:24:14 +02:00
Lennart Poettering d4a70ecc31 dissect-image: unlock LUKS partitions in DDIs via enrolled TPM2 tokens (#44132) 2026-10-14 09:36:29 +02:00
Paul Meyer 7d37482ce4 tpm2-util: fall back to a PCR policy for NvPCR initialization
If the booted UKI carries no PCR public key or no signed policy with
the "initrd" reference, initialize NvPCRs in the initrd with a
PolicyPCR init policy bound to the current value of PCR 11 instead of
not initializing them at all.

The resulting NvPCR names depend on PCR 11 and hence change with every
UKI update, so this is only useful where PCR 11 can be predicted.

Signed-off-by: Paul Meyer <katexochen0@gmail.com>
2026-10-13 20:41:53 +02:00
Adrian Reber 600fcc6dcb dissect,nspawn,sysext: enable TPM2 unlocking of DDIs, document it
Set DISSECT_IMAGE_TPM2_UNLOCK where unlocking an image's LUKS partitions
via the local TPM2 is wanted and the caller is trusted:

 * systemd-dissect, an admin tool operating on an image the invoking user
   can read anyway;
 * systemd-nspawn --image=, which already prompts for a passphrase
   interactivly, so TPM2 first and passphrase second is the natural
   order;
 * systemd-sysext/systemd-confext, which decrypt without any passphrase,
   so extension images sealed to the host can be activated without user
   interaction.

For sysext/confext setting the flag at merge time is not enough: before
merging, the extension-release metadata is read via image_read_metadata()
in discover-image.c, which uses its own flag set and would already fail
with -ENOKEY on an encrypted image. Give it an extra_flags parameter and
pass the flag from there, too; the other callers (machined, portabled)
pass 0 and keep their behaviour.

Two units need adjusting for this to work when started by the service
manager: systemd-nspawn@.service has DevicePolicy=closed, so allow
/dev/tpmrm0 there, and the sysext/confext services are not ordered
against the TPM2 device showing up, so order them after tpm2.target
like the pcr* services. The initrd variants cannot be ordered the same
way: they run before local-fs-pre.target, while the software TPM fallback
only becomes available after the early ESP mount, which is ordered after
local-fs-pre.target, so a static After=tpm2.target would be an ordering
cycle with systemd.tpm2_software_fallback=1. Hence systemd-tpm2-generator
adds the ordering as a drop-in instead, unless the fallback is in use.
That drop-in also orders them after systemd-pcrphase-initrd.service:
nothing else guarantees the "enter-initrd" phase has been measured into
PCR 11 before the initrd extension units merge their images (the barrier's
Before=systemd-sysext.service is a leftover from when that unit was also
used in the initrd), so tokens bound to a signed PCR 11 policy or a
pcrlock policy would race the measurement.

Deliberately not enabled for now: RootImage=/ExtensionImages=/MountImages=
in units, portabled and gpt-auto. For those an unconditional default is
probably not wanted but a per-unit or per-image switch, which is left for
a follow-up. systemd-mountfsd, which unprivileged systemd-dissect and
systemd-nspawn delegate to, keeps its own flag set and does not honour
the flag, hence TPM2 unlocking is only available when running privileged;
the man pages say so.

Document the behaviour and $SYSTEMD_DISSECT_TPM2_UNLOCK= in the dissect,
nspawn and sysext man pages and in docs/ENVIRONMENT.md.
2026-10-13 11:05:48 +00:00
Yu Watanabe 6d8af5c208 udev-watch: reimplement with fanotify
Replace the inotify + /run/udev/watch/ symlink machinery with fanotify inode
marks (FAN_CLOSE_WRITE). The point is not merely a different backend; fanotify
removes several structural costs that inotify imposed on udevd:

- An inotify event only identifies the watch by a watch descriptor, which udevd
  had to translate back to a device. That mapping was maintained as a table of
  symlinks under /run/udev/watch/. A fanotify event instead carries the watched
  inode's file handle (FAN_REPORT_FID), which is resolved to the device directly
  via open_by_handle_at()+fstat(). The wd->device translation, and with it
  /run/udev/watch/ entirely, is no longer needed.

- Without that shared symlink store to coordinate, a worker can add and remove
  its own device marks directly on the fanotify group fd. Previously the watch
  state was owned by the manager, and workers had to request (un)registration
  over the notification socket (sd_notify()+SIGUSR1). Dropping that round-trip
  both simplifies the code and is expected to be faster.

- A fanotify mark lives on the inode and is dropped by the kernel once the inode
  is gone, so the special handling for removed device nodes is no longer needed.

The group fd is handed over across restarts via the service manager's fd store
and the kernel keeps the marks, so nothing is rebuilt in-process; the fd is also
propagated to each worker. Watches left behind by an older, inotify-based udevd
under /run/udev/watch/ are migrated to fanotify marks on first start, then the
directory is removed.

Device watch falls back to inotify on kernels < v5.13, when CONFIG_SHMEM=n
(devtmpfs backed by ramfs), or when CONFIG_FANOTIFY is disabled. This fallback
can also be forced via $SYSTEMD_UDEV_USE_INOTIFY.
2026-10-12 04:04:37 +09:00
Zbigniew Jędrzejewski-Szmek 2f86c31060 meson: add option -Dexperimental=
The enablement has two levels:
- at compilation time, setting -Dexperimental=disabled disables the
  features completely. The idea is that we can compile code out if
  that is set. -Dexperimental=enabled disables the check completely.
  -Dexperimental=envvar allows use if the variable is set.
  -Dexperimental=auto is translated to envvar in developer mode, and
  envvar otherwise.
- at runtime, if not disabled, the envvar is checked first
  (always has priority over the compiled-in default), and then the
  compile-time default is used.

If denied, the user gets an error message.

This is just meson and build.h plumbing + docs.
2026-10-07 17:09:36 +02:00
Daan De Meyer 6498ae063d CODING_STYLE: handle errors before the success path
Code in the tree handles an error in an if (r < 0) block that returns, and
continues with the success path after it. CODING_STYLE.md does not mention
the pattern. Document it with an example.
2026-10-06 10:19:17 +02:00
cksrb63 26bde2b760 docs: fix stale links 2026-10-05 09:35:58 +02:00
Daan De Meyer 643b93185c Extend the AI policy a bit
Inspired by the text from https://github.com/jj-vcs/jj/blob/main/AI_POLICY.md.

- We add a section on not using LLM's to communicate.
- We relax the language on using AI to design/write code a bit. The main emphasis
  is put on understanding what you're submitting. It's fine if AI designed it
  and wrote it, but you as the author are supposed to fully understand and be able
  to answer questions about it.
2026-10-03 16:12:54 +02:00
Daan De Meyer d00574c5f6 Move subsystem maintainers to CODEOWNERS
Let's maintain the list of subsystem maintainers
in CODEOWNERS, which github knows about and can do
useful stuff with like automatically adding those
usernames as reviewers.
2026-10-02 14:58:43 +02:00
Daan De Meyer 55c8c79507 docs: Add doc for describing the meaning of github labels
Add a description for the new good-to-merge/trust-me-bro
label.
2026-10-02 14:56:31 +02:00
WilliButz cfb11e1feb docs: mention LoaderInfo efivar in BLI 2026-10-02 12:52:24 +02:00
Lennart Poettering ce8d684ed8 sysinstall: optionally, automatically pick target block device after a settle timeout
Let's make sysinstall useful for truly unattended installations, and let
it it automatically pick a target disk after some settlement time-out.
2026-09-23 10:14:25 +02:00
Zbigniew Jędrzejewski-Szmek a415aeb1d2 docs: fix typo 2026-09-22 18:46:41 +02:00
Yu Watanabe 496712eddc docs: fix typos and grammar in various documents 2026-09-17 11:49:45 +09:00
zouge666 eb020fc492 import: merge default OpenPGP keyrings
When an administrator installed a custom keyring under /etc,
signature verification selected it instead of the vendor keyring
under /usr. That could make vendor-signed system updates stop
verifying after adding local keys.

Collect all readable default keyrings, including the current and
legacy /etc paths, and pass temporary copies to GnuPG with
separate --keyring options. Keep SYSTEMD_OPENPGP_KEYRING as an
explicit override, add regression coverage for keyring
coexistence, override behavior, and current-path signing, and
silence the expected shellcheck false positive in the test
cleanup helper.

Closes: #40702
2026-08-26 11:35:55 +01:00