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)
* 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)
* 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)
* 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)
This partially reverts 77b3ddf2aa.
Testing with musl is now done by postmarketOS. Hence, these packages
are not necessary anymore.
(cherry picked from commit fd1f164b1b)
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)
As per review comments on https://github.com/systemd/systemd/pull/33394
Follow-up for: 6e12c598d34eb9345d8c000f1abe790f4d79c5c5
(cherry picked from commit cc76554de0736ec5623635493cb238620c589da8)
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)
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)
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)
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)
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)
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)
varlinkctl no longer stays silent if an object is empty, and that broke
some tests
(cherry picked from commit 8904b844a43e21530d82a39bbd51c3d9847e5426)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
THe limits are hit with valid configurations, hence raise the limits
4x.
Fixes: #44125
(cherry picked from commit 116981d536f52279715df266098bf3093037fc3f)
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)
EV_EFI_HANDOFF_TABLES and EV_EFI_HANDOFF_TABLES2 are both defined with
the same name.
(cherry picked from commit 195a17c59b22f5b0fa626fdb4917107cdc281bac)
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)
- 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)
"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)
Then, added explanations for the missing arguments. Also mentioned that
the memfd is sealed by the function.
(cherry picked from commit 20604d980057da1a606339fb7a660242e8d2db02)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
- 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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
For consistency with ssh-issue output, do not log about the CID if it is
not a usable destination.
(cherry picked from commit 0d59bcb6944d1f34e8eca9208af198f5357e8535)
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)
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)
Both attach and reattach must fail, and the latter must not detach the
image first.
(cherry picked from commit 430f8962cf2e454cc9b474a22b92a89a26872e9b)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
... 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)
... 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)
... in `write_membership()` function.
Log the actual error message returned from `chase_and_open()`.
(cherry picked from commit 513e4b9947c619e2ecfe79c0e81d6461dc65480c)
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)
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)
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)
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)
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)
%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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
# 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` |
| `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.
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.
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/).
_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.
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.
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.
Take possession of each seat by spawning your greeter on it.
<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>
# Until -mgeneral-regs-only is supported in LoongArch, use the following option instead:
'loongarch64':['-mno-lsx','-mno-lasx'],
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.