In #39675 the reported fail was as follows:
5580s [ 247.559994] TEST-13-NSPAWN.sh[1858]: Exported 93%.
5580s [ 247.659002] TEST-13-NSPAWN.sh[1858]: Exported 95%.
5580s [ 247.785893] TEST-13-NSPAWN.sh[1858]: Operation completed successfully.
5580s [ 247.923727] TEST-13-NSPAWN.sh[1858]: Exiting.
5580s [ 258.300406] TEST-13-NSPAWN.sh[1074]: + machinectl import-raw /var/tmp/container-export.raw container-raw-reimport
5580s [ 258.323328] TEST-13-NSPAWN.sh[1884]: The 'machinectl import-raw' command has been replaced by 'importctl -m import-raw'. Redirecting invocation.
5580s [ 258.659982] TEST-13-NSPAWN.sh[1884]: Failed to transfer image: Remote peer disconnected
5580s [ 258.734218] TEST-13-NSPAWN.sh[1074]: + at_exit
Turns out that the real reason behind this fail is that the machine was
under heavy load due to a busy-loop from the stub init. The cause of
this is a bug in bash, where running commands that fork (i.e. not
built-ins) can cause a permanent busy-loop due to a desync in trap
handling if you send the signals to the bash process _just right_:
[ 90.855318] TEST-13-NSPAWN.sh[1074]: + machinectl poweroff long-running long-running long-running
[ 90.855318] TEST-13-NSPAWN.sh[1074]: + machinectl reboot long-running long-running long-running
[ 90.928980] systemd-nspawn[1679]: ++ touch /poweroff
[ 90.928980] systemd-nspawn[1679]: +++ touch /reboot
[ 90.928980] systemd-nspawn[1679]: + :
[ 90.928980] systemd-nspawn[1679]: + :
[ 90.928980] systemd-nspawn[1679]: + wait
[ 90.928980] systemd-nspawn[1679]: + :
[ 90.928980] systemd-nspawn[1679]: + :
[ 90.928980] systemd-nspawn[1679]: + wait
[ 90.928980] systemd-nspawn[1679]: + :
[ 90.928980] systemd-nspawn[1679]: + :
[ 90.928980] systemd-nspawn[1679]: + wait
...
$ journalctl --file TEST-13-NSPAWN-1.journal -o short-monotonic --no-hostname --grep "^\+ wait$" | wc -l
349734
So the stub-init was hammering the machine in a tight endless loop,
which then caused systemd-importd to timeout when talking to D-Bus:
[ 258.300096] TEST-13-NSPAWN.sh[1074]: + machinectl import-raw /var/tmp/container-export.raw container-raw-reimport
...
[ 258.415319] systemd-importd[1859]: Unable to request name, failing connection: Method call timed out
[ 258.483662] systemd-importd[1859]: Bus n/a: changing state RUNNING → CLOSING
[ 258.605442] systemd-importd[1859]: Bus n/a: changing state CLOSING → CLOSED
[ 258.659958] TEST-13-NSPAWN.sh[1884]: Failed to transfer image: Remote peer disconnected
Given this is not our issue, let's work around it by using just
built-ins from the trap handlers, which are not susceptible to this bug.
Resolves: #39675
(cherry picked from commit 4d92c72b81)
(cherry picked from commit d1f98dffb3)
If a journal file contains a truncated ZSTD frame (i.e. a frame with
Frame_Content_Size > 0, but with not enough data in Data_Block),
ZSTD_decompressStream() would return a non-zero, non-error value. This
would then skip the error path in the ZSTD_isError() branch and we'd hit
the following assert:
$ build-local/journalctl -o cat --file zstd-truncated.journal
Assertion 'output.pos >= prefix_len + 1' failed at src/basic/compress.c:1236, function decompress_startswith_zstd(). Aborting.
Aborted (core dumped) build-local/journalctl -o cat --file zstd-truncated.journal
Let's handle this situation gracefully and return EBADMSG instead.
Also, add another journalctl invocation to the corrupted-journals test
that goes through the sd_journal_get_data() -> decompress_startswith_zstd()
code path which, among other things, covers the issue when run on the
provided journal file.
(cherry picked from commit 35eb598af2)
(cherry picked from commit a9cfbed091)
Otherwise `journalctl --directory=` skips over them in the second part of
the test.
(cherry picked from commit e869c83367)
(cherry picked from commit 7a83d5cc3c)
Ensure only privileged users can call the system scope machined's
APIs that get data out of a machine
Follow-up for 1bd979dddb
Follow-up for 9153b02bb5
(cherry picked from commit 3e716178cc)
(cherry picked from commit 6e6aa47f46)
Otherwise you run into errors such as:
"""
../meson.build:2899:28: ERROR: File src/test/test-loop-util.c does not exist.
"""
when deleting a file in git without staging the deletion.
(cherry picked from commit 8355eb6e11)
(cherry picked from commit 06a12ba00b)
TEST-74-AUX-UTILS has a number of subtests.
test/units/TEST-74-AUX-UTILS.capsule.sh runs first and starts and stops
capsule@foobar.service. Looking at the test, the unit is cleanly stopped.
But later test/units/TEST-74-AUX-UTILS.machine-id-setup.sh tests for
failed units. capsule@foobar.service is listed as failed, causing the
second subtest to fail.
Add the same test in test/units/TEST-74-AUX-UTILS.capsule.sh to see
if the failed test really originates from there.
(cherry picked from commit 71c15cdbea)
(cherry picked from commit 76f0f08970)
When systemd-cryptenroll --tpm2-device=auto is called on a system where
a tpm2-pcr-public-key.pem exists it automatically creates tokens with a
signed PCR policy. Unlocking such a token via --unlock-tpm2-device=auto
requires a tpm2-pcr-signature.json file, which is not present.
This creates a race with systemd-tpm2-setup.service at boot: if the
service completes before the test, the key exists and the subsequent
--unlock-tpm2-device=auto calls fail, which I believe is the cause of
the test flakiness.
This also seems to mesh with the fact that this only flakes on Debian
CI, since that's built with ukify which installs a public key.
Let's hopefully fix this by passing --tpm2-public-key= to all
--tpm2-device= enrollment calls that aren't explicitly intended to test
signed PCR policy behaviour.
(cherry picked from commit cd18656d47)
(cherry picked from commit 94e8cac341)
While we're at it, rename to test-loop-util.c so it matches its
source file.
We also drop the root check and solely check for CAP_SYS_ADMIN since
that's sufficient to run the tests.
(cherry picked from commit d49df940ec)
(cherry picked from commit 74679d3d1f)
During daemon-reload (or daemon-reexec), when a unit becomes an alias to
another unit, deserialising the alias's stale serialised state can
corrupt the canonical unit's live runtime state.
Consider this scenario:
1. Before reload:
- a.service is running
- b.service was stopped earlier and is dead
- Both exist as independent units
2. User creates an alias to migrate from b -> a:
- `ln -s /run/systemd/system/a.service /etc/systemd/system/b.service`
3. daemon-reload triggers serialisation. State file contains both units:
- a.service -> state=running, cgroup=/system.slice/a.service,
PID=1234, ...
- b.service -> state=dead, cgroup=(empty), no PIDs, ...
4. During deserialisation:
- Processes a.service: loads Unit A, deserialises -> state=RUNNING
- Processes b.service: manager_load_unit() detects symlink, returns
Unit A
- unit_deserialize_state(Unit A, ...) overwrites with b's dead state
5. The result is that:
- Unit A incorrectly shows state=dead despite PID 1234 still running
- If a.service has Upholds= dependents, catch-up logic sees
a.service should be running but is dead
- systemd starts a.service again -> PID 5678
- Two instances run: PID 1234 (left-over) and PID 5678 (new)
This bug is deterministic when serialisation orders a.service before
b.service.
The root cause is that manager_deserialize_one_unit() calls
manager_load_unit(name, &u) which resolves aliases via
unit_follow_merge(), returning the canonical Unit object. However, the
code doesn't distinguish between two cases when u->id differs from the
requested name from the state file. In the corruption case, we're
deserialising an alias entry and unit_deserialize_state() blindly
overwrites the canonical unit's fields with stale data from the old,
independent unit. The serialised b.service then overwrites Unit A's
correct live state.
This commit first scans the serialised unit names, then adds a check
after manager_load_unit():
if (!streq(u->id, name) && set_contains(serialized_units, u->id))
...
This detects when the loaded unit's canonical ID (u->id) differs from
the serialised name, indicating the name is now an alias for a different
unit and the canonical unit also has its own serialised state entry.
If the canonical unit does not have its own serialised state entry, we
keep the state entry. That handles cases where the old name is really
just a rename, and thus the old name is the only serialised state for
the unit. In that case there is no bug, because there is no separate
canonical state entry for the stale alias entry to overwrite.
Skipping is safe because:
1. The canonical unit's own state entry will be correctly deserialised
regardless of order. This fix only prevents other stale alias entries
from corrupting it.
2. unit_merge() has already transferred the necessary data. When
b.service became an alias during unit loading, unit_merge() already
migrated dependencies and references to the canonical unit.
3. After merging, the alias doesn't have its own runtime state. The
serialised data represents b.service when it was independent, which
is now obsolete once the canonical unit also has its own serialised
entry.
4. All fields are stale. unit_deserialize_state() would overwrite state,
timestamps, cgroup paths, pids, etc. There's no scenario where we
want this data applied on top of the canonical unit's own serialised
state.
This fix also correctly handles unit precedence. For example, imagine
this scenario:
1. `b.service` is a valid, running unit defined in `/run`.
2. The sysadmin creates `ln -s .../a.service /etc/.../b.service`.
3. On reload, the new symlink in `/etc` overrides the unit in `/run`.
The new perspective from the manager side is that `b.service` is now an
alias for `a.service`.
In this case, systemd correctly abandons the old b.service unit, because
that's the intended general semantics of unit file precedence. We also
do that in other cases, like when a unit file in /etc/systemd/system/
masks a vendor-supplied unit file in /lib/systemd/system/, or when an
admin uses systemctl mask to explicitly disable a unit.
In all these scenarios, the configuration with the highest precedence
(in /etc/) is treated as the new source of truth. The old unit's
definition is discarded, and its running processes are (correctly)
abandoned. In that respect we are not doing anything new here.
Some may ask why we shouldn't just ignore the symlink if we think this
case will come up. I think there are multiple very strong reasons not to
do so:
1. It violates unit precedence. The unit design is built on a strict
precedence list. When an admin puts any file in /etc, they are
intentionally overriding everything else. If manager_load_unit were
to "ignore" this file based on runtime state, it would break this
fundamental precedent.
2. It makes daemon-reload stateful. daemon-reload is supposed to be a
simple, stateless operation, basically to read the files on disk and
apply the new configuration. But doing this would make daemon-reload
stateful, because we'd have to read the files on disk, but
cross-reference the current runtime state, and... maybe ignore some
files. This is complex and unpredictable.
3. It also completely ignores the user intent. The admin clearly has
tried to replace the old service with an alias. Ignoring their
instruction is the opposite of what they want.
Fixes: https://github.com/systemd/systemd/issues/38817
Fixes: https://github.com/systemd/systemd/issues/37482
(cherry picked from commit a77c7a8224)
(cherry picked from commit bdd5b0c3ea)
In Ubuntu 26.04 the actual binary is called gnusleep, and sleep is a symlink,
so fix the regex exclusion for the coredump checks
(cherry picked from commit f737b38977)
(cherry picked from commit ecf27a3eef)
Ubuntu is doing shenanigans with their coreutils so they are now
symlinks instead of binaries, so the grep fails. Check bash instead
to fix test failure on 26.04.
(cherry picked from commit 9f56d62f92)
(cherry picked from commit 8f06afa8c9)
[] has higher precedence than pointer dereference, hence hilarity
ensues as soon as there are multuple images
Originally reported on yeswehack.com as:
YWH-PGM9780-122
Follow-up for dfdeb0b1cb
(cherry picked from commit 0c67b8adcb)
bus_cgroup_set_tasks_max_scale() used a hand-rolled percentage format
that produced values ~10x too small (e.g., "TasksMax=4.0%" instead of
"TasksMax=40.00%").
On daemon-reload, the incorrect value was re-read, silently reducing
the effective TasksMax by ~10x and causing fork rejections on systems
with high thread counts.
Fix by using the existing PERMYRIAD macros, consistent with memory
property handlers (MemoryMax, MemoryHigh, MemoryLow, etc.).
Fixes: #41009
(cherry picked from commit 9d15e09d5c)
1 and 10000 are valid cgroup weight values, but the condition was
incorrectly excluding them:
$ echo '{"userName":"crashhostarray","cpuWeight":1}' | userdbctl -F -
<stdin>:1:42: JSON field 'cpuWeight' is not in valid range 1…10000.
$ echo '{"userName":"crashhostarray","cpuWeight":10000}' | userdbctl -F -
<stdin>:1:42: JSON field 'cpuWeight' is not in valid range 1…10000.
(cherry picked from commit 76ab7861ff)
/run/systemd/inaccessible/ exists only on host - in the container we have
/run/host/inaccessible/, and since all the inaccessible mounts have
MOUNT_IN_USERNS we need to use the latter one, otherwise the masking
gets silently skipped:
~# SYSTEMD_LOG_LEVEL=debug systemd-nspawn -q --directory=foo ls -la /proc/kallsyms
...
Bind-mounting /run/systemd/inaccessible/reg on /proc/kallsyms (MS_BIND "")...
Failed to mount /run/systemd/inaccessible/reg (type n/a) on /proc/kallsyms (MS_BIND ""): No such file or directory
Changing mount flags /proc/kallsyms (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_REMOUNT|MS_BIND "")...
Failed to mount n/a (type n/a) on /proc/kallsyms (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_REMOUNT|MS_BIND ""): Invalid argument
Bind-mounting /run/systemd/inaccessible/reg on /proc/kcore (MS_BIND "")...
Failed to mount /run/systemd/inaccessible/reg (type n/a) on /proc/kcore (MS_BIND ""): No such file or directory
Changing mount flags /proc/kcore (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_REMOUNT|MS_BIND "")...
Failed to mount n/a (type n/a) on /proc/kcore (MS_RDONLY|MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_REMOUNT|MS_BIND ""): Invalid argument
...
Inner child finished, invoking payload.
-r--r--r--. 1 root root 0 Feb 25 13:19 /proc/kallsyms
(cherry picked from commit 83b8daa032)
Forbid non-root from shelling into a machine that is running in
the root user namespace.
Follow-up for adaff8eb35
(cherry picked from commit e5a5656b55)
The echo builtin provided by some shells (mksh) will interpret \x2d as
an escape sequence. This causes meson to fail:
```
test/fuzz/meson.build:93:52: ERROR: File fuzz-unit-file/dm-back-slash.swap does not exist.
```
Bug: https://bugs.gentoo.org/969789
(cherry picked from commit a304f6c9db)
In my testing I switched building my locally run CI integration tests to
ArchLinux and realized that for that the default sizes don't work
anymore, the images are larger than the space allocated. Let's bump the
size by 50% for the relevant disk images.
(cherry picked from commit ab89fad427)
Let's use truncate -s … to create empty files (if they can be sparse)
Let's use fallocate -l … to create empty non-sparse files.
This should reduce the disk footprint of our tests a bit, given that in
most cases we won't use the allocate disk space in full, not even
remotely.
(cherry picked from commit dd2676c1ab)
Otherwise on SELinux enabled systems with the "targeted" policy
the type is not set correctly when run via unconfined user and
the test fails.
(cherry picked from commit d3761f1509)
ref_uid is initialized to invalid, and is only set in some
circumstances. The AttachProcesses will attempt to check it,
and assert that it is valid. Check beforehand.
Reported as YWH-PGM9780-89
Follow-up for 59857b672c
(cherry picked from commit 05f5156ad1)
This reverts (in sprit) commit f5cdf9515a,
"udev-rules: ignore non-system user/group in OWNER=/GROUP=".
The original change was done to clean up a situation where we added a
new group, but the group could already have been used for some other
purposes, and now the some unexpected entity would own the device.
Unfortunately, this check doesn't really address the issue, since the
existing account might as well be a system account, which might be
equally bad. In addition, this change is a big compatiblity break,
causing existing rules to stop working. Since quite a lot of systems
have local configuration to assign devices to users for various
purposes, this is very noticable to users. In a way, the original change
to add a new group was the compat break, and follow-up patch to cahnge
the rule parsing evolved a small compat break into a much bigger one.
There is merit to the change though, since device nodes shouldn't be
owned by users and groups and different mechanisms should be used
instead. To avoid breaking users systems, and since the original goal
cannot be achieved by this patch, let's downgrade this to a warning
to guide users towards different solutions.
(cherry picked from commit 5c05a339c6)
Then, let's make syslog_parse_identifier() returns PID as pid_t, rather
than the string.
This also makes the function refuse ridiculously long identifier.
Fixes#40456.
Fixes oss-fuzz#477990732 (https://issues.oss-fuzz.com/issues/477990732).
(cherry picked from commit eb5b797d7c)
Partially reverts d6b3793704.
On Ubuntu 26.04 devel, TEST-75-RESOLVED often fails at this stage,
despite the matching query apparently being found:
+ monitor_check_rr '2025-12-18 16:02:54' 'follow10.so.close.signed.test IN CNAME follow11.yet.so.far.signed.test'
+ set +x
Dec 18 16:02:54 ns1.unsigned.test resolvectl[552]: ← A: follow10.so.close.signed.test IN CNAME follow11.yet.so.far.signed.test
+ monitor_check_rr '2025-12-18 16:02:54' 'follow11.yet.so.far.signed.test IN CNAME follow12.getting.hot.signed.test'
+ set +x
Dec 18 16:02:54 ns1.unsigned.test resolvectl[552]: ← A: follow11.yet.so.far.signed.test IN CNAME follow12.getting.hot.signed.test
+ monitor_check_rr '2025-12-18 16:02:54' 'follow12.getting.hot.signed.test IN CNAME follow13.almost.final.signed.test'
+ set +x
Dec 18 16:02:54 ns1.unsigned.test resolvectl[552]: ← A: follow12.getting.hot.signed.test IN CNAME follow13.almost.final.signed.test
+ monitor_check_rr '2025-12-18 16:02:54' 'follow13.almost.final.signed.test IN CNAME follow14.final.signed.test'
+ set +x
Dec 18 16:02:54 ns1.unsigned.test resolvectl[552]: ← A: follow13.almost.final.signed.test IN CNAME follow14.final.signed.test
Unsetting pipefail, as was done before d6b3793704, appears to fix the
problem.
(cherry picked from commit 7c9c34514a)
With GNU coreutils, one can pass an argument to the "set" flag like:
date -s "-3 days"
With uutils coreutils, that gives an error:
error: unexpected argument '-3' found
tip: to pass '-3' as a value, use '-- -3'
That's a bug (https://github.com/uutils/coreutils/issues/9679), but both
implementations accept --set="-3 days" just fine, so use that instead.
(cherry picked from commit 9dcfd6e8fe)
On Ubuntu's test infrastructure for the development series, this test
often fails when piping the journal output to head. The cause is
unclear, but possibly related to Ubuntu's use of uutils coreutils.
Workaround this by just using journalctl's -n flag, which removes the
need for piping output to head.
(cherry picked from commit a8efad14f8)
User and group systemd-network are created from
sysusers.d/systemd-network.conf, which is only copied into the test
image when building with -Dnetworkd=true. This means that if
-Dnetworkd=false is used, the user and the group don't exist, which
causes the test to fail.
Use a locally created user and group to avoid that.
(cherry picked from commit a11278ce63)
Follow-up for 7bf0d0c46e.
To support e2fsprogs older than v1.47.1 (released 2024-05-21).
Suggested-by: ZauberNerd <zaubernerd@zaubernerd.de>
(cherry picked from commit 7d23749ddd)