1
0
mirror of https://github.com/systemd/systemd synced 2025-11-10 20:34:45 +01:00

Compare commits

...

65 Commits

Author SHA1 Message Date
cvlc12
380f0b0b5d man: systemd-measure. Remove 'tpm2-pcrs=' from cryptenroll command (#39590)
This is now default since 4b840414be3b2d6520599d86d2b718a37574aabf.

(cherry picked from commit c3e80f8f2bbd2b79350684f52638cedec00eb8ad)
2025-11-06 23:38:13 +00:00
jouyouyun
83f3c4d4d7 nss-systemd: fix memory leak
(cherry picked from commit 9ebf0d260da18fd84e2f3d587895a82803ed99e2)
2025-11-06 23:38:13 +00:00
David Tardon
df708956b0 ask-password-api: return if read_credential() failed
The current code causes assertion in strv_parse_nulstr() if
read_credential() results in an error different from ENXIO or ENOENT
(strace shows I'm getting EACCES):

 # homectl create waldo --real-name=Waldo --disk-size=200M

Before:

 Assertion 's || l <= 0' failed at src/basic/nulstr-util.c:32, function strv_parse_nulstr_full(). Aborting.

After:

 Failed to acquire password: Permission denied

Follow-up-for: 8806bb4bc7fa15d6ca46e81b8d535730209a3b66
(cherry picked from commit 399c9f847e222d6e62c553ac9ea2bebeb7c1be7f)
2025-11-06 23:38:13 +00:00
David Tardon
a248717cd2 homectl: fix memory leak
# valgrind --leak-check=full homectl create waldo --real-name=Waldo --disk-size=200M --setopt=FOO=bar

Before:

==25155== HEAP SUMMARY:
==25155==     in use at exit: 12,879 bytes in 39 blocks
==25155==   total heap usage: 90 allocs, 51 frees, 53,964 bytes allocated
==25155==
==25155== 8 bytes in 1 blocks are definitely lost in loss record 4 of 38
==25155==    at 0x4845866: malloc (vg_replace_malloc.c:446)
==25155==    by 0x547FC2E: strdup (strdup.c:42)
==25155==    by 0x4B2647C: strv_env_replace_strdup_passthrough (env-util.c:435)
==25155==    by 0x42D547: parse_argv (homectl.c:3909)
==25155==    by 0x43999C: run (homectl.c:5606)
==25155==    by 0x4399F5: main (homectl.c:5613)
==25155==
==25155== LEAK SUMMARY:
==25155==    definitely lost: 8 bytes in 1 blocks

After:

==25224== HEAP SUMMARY:
==25224==     in use at exit: 12,871 bytes in 38 blocks
==25224==   total heap usage: 90 allocs, 52 frees, 53,964 bytes allocated
==25224==
==25224== LEAK SUMMARY:
==25224==    definitely lost: 0 bytes in 0 blocks

Follow-up-for: aaf057c4bbc6055040d7d2c1ec3655ff89249ebd
(cherry picked from commit 5efcbae259826a184dc962822a4e060a21f5175c)
2025-11-06 23:38:13 +00:00
Christoph Anton Mitterer
82850b88f6 man: clarify what “failed” means
systemd.service(5)’s documentation of `ExecCondition=` uses “failed” with
respect to the unit active state.
In particular the unit won’t be considered failed when `ExecCondition=`’s
command exits with a status of 1 through 254 (inclusive). It will however, when
it exits with 255 or abnormally (e.g. timeout, killed by a signal, etc.).

The table “Defined $SERVICE_RESULT values” in systemd.exec(5) uses “failed”
however rather with respect to the condition.

Tests seem to have shown that, if the exit status of the `ExecCondition=`
command is one of 1 through 254 (inclusive), `$SERVICE_RESULT` will be
`exec-condition`, if it is 255, `$SERVICE_RESULT` will be `exit-code` (but
`$EXIT_CODE` and `$EXIT_STATUS` will be empty or unset), if it’s killed because
of `SIGKILL`, `$SERVICE_RESULT` will `signal` and if it times out,
`$SERVICE_RESULT` will be `timeout`.

This commit clarifies the table at least for the case of an exit status of 1
through 254 (inclusive).
The others (signal, timeout and 255 are probably also still ambiguous (e.g.
`signal` uses “A service process”, which could be considered as the actual
service process only).

Signed-off-by: Christoph Anton Mitterer <mail@christoph.anton.mitterer.name>
(cherry picked from commit 07f471824288433d17ebe097e94dfca85e74fea6)
2025-11-06 23:38:13 +00:00
jouyouyun
2ccbc76efb nss-resolve: fix the ip addr family validity check method
`i` only counts the number of matches with the current family,
while `n_addresses` counts the number of matches with the family INET or INET6.
If the address contains both INET and INET6, `assert(i == n_addresses)` will fail.

(cherry picked from commit fea7f5d68b5a6272ce8989e872a57b42121b5205)
2025-11-06 23:38:13 +00:00
Nils K
9a4618259f man: fix username prefix mentioned in manual for capsule users (#39573)
(cherry picked from commit bea3b300bc07271664e0c6f8b73c6e049df9aa1a)
2025-11-06 23:38:13 +00:00
Luca Boccassi
6afa11c8fa test: ensure test checking status runs first
The test messes a bit with the ESP, which might cause bootctl status output to change.
Run the test that simply checks status without changing anything first.

[  188.633908] TEST-87-AUX-UTILS-VM.sh[1101]: + bootctl status --quiet
[  188.681082] TEST-87-AUX-UTILS-VM.sh[1155]: System:
[  188.681082] TEST-87-AUX-UTILS-VM.sh[1155]:       Firmware: UEFI 2.70 (EDK II 1.00)
[  188.681082] TEST-87-AUX-UTILS-VM.sh[1155]:  Firmware Arch: x64
[  188.681082] TEST-87-AUX-UTILS-VM.sh[1155]:    Secure Boot: enabled (user)
<...>
[  198.938717] TEST-87-AUX-UTILS-VM.sh[1679]: ++ printf '\6\0\0\0\1'
[  198.939235] TEST-87-AUX-UTILS-VM.sh[1678]: + cmp /sys/firmware/efi/efivars/SecureBoot-8be4df61-93ca-11d2-aa0d-00e098032b8c /dev/fd/63
[  198.944957] TEST-87-AUX-UTILS-VM.sh[1678]: + cmp /sys/firmware/efi/efivars/SetupMode-8be4df61-93ca-11d2-aa0d-00e098032b8c /dev/fd/63
[  198.945808] TEST-87-AUX-UTILS-VM.sh[1681]: ++ printf '\6\0\0\0\0'
[  198.950459] TEST-87-AUX-UTILS-VM.sh[1684]: + bootctl status
[  198.951357] TEST-87-AUX-UTILS-VM.sh[1685]: + grep -q 'Secure Boot: enabled'
[  199.004142] TEST-87-AUX-UTILS-VM.sh[1086]: + echo 'Subtest /usr/lib/systemd/tests/testdata/units/TEST-87-AUX-UTILS-VM.bootctl.sh failed'

Follow-up for 5ae58ac2b93a4046fbae4e0c825b8cc9d03d10d8

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

(cherry picked from commit 7a62cbfc6d1ca687ac5bceb63356ae1faf34be1e)
2025-11-06 23:38:13 +00:00
Frantisek Sumsal
86fe18ddcf test: sync journal after the test unit finishes
In these two cases we need to sync the journal _after_ the unit finishes
as well, because we try to match messages from systemd itself, not
(only) from the unit, and the messages about units are dispatched
asynchronously.

That is, in the first case (silent-success.service) we want to make sure
that LogLevelMax= filters out messages _about_ units (from systemd) as
well, including messages like "Deactivated..."  and "Finished...", which
are sent out only when/after the unit is stopped.

In the second case we try to match messages with the "systemd" syslog
tag, but these messages come from systemd (obviously) and are sent out
asynchronously, which means they might not reach the journal before we
call `journalctl --sync` from the test unit itself, like happened here:

[ 1754.150391] TEST-04-JOURNAL.sh[13331]: + systemctl start verbose-success.service
[ 1754.172256] bash[13692]: success
[ 1754.221210] TEST-04-JOURNAL.sh[13694]: ++ journalctl -b -q -u verbose-success.service -t systemd
[ 1754.221493] TEST-04-JOURNAL.sh[13331]: + [[ -n '' ]]
[ 1754.175709] systemd[1]: Starting verbose-success.service - Verbose successful service...
[ 1754.221697] TEST-04-JOURNAL.sh[122]: + echo 'Subtest /usr/lib/systemd/tests/testdata/units/TEST-04-JOURNAL.journal.sh failed'
[ 1754.221697] TEST-04-JOURNAL.sh[122]: Subtest /usr/lib/systemd/tests/testdata/units/TEST-04-JOURNAL.journal.sh failed
[ 1754.221697] TEST-04-JOURNAL.sh[122]: + return 1
[ 1754.205408] systemd[1]: verbose-success.service: Deactivated successfully.
[ 1754.205687] systemd[1]: Finished verbose-success.service - Verbose successful service.

By syncing the journal after the unit is stopped we have much bigger
chance that the systemd messages already reached the journal - the race
is technically still there, but the chance we'd hit it should be pretty
negligible.

Resolves: #39555
(cherry picked from commit 7b3046e693cef3e0ce54058852deb8148254bba7)
2025-11-06 23:38:13 +00:00
Frantisek Sumsal
61bd310be9 test: wait for the backgrounded socat job
It should exit on its own anyway and this will work even if the job has
already finished* (unlike kill).

[*] assuming job control is off, as it's the case when running the
    test suite

Resolves: #39543
(cherry picked from commit 3849b0701a7713c147400f205e7ddb3e3f93ad26)
2025-11-06 23:38:13 +00:00
Frantisek Sumsal
64ac3f1879 test: wait until the nspawn process is completely dead
Before calling io.systemd.MachineImage.List.

The systemd-nspawn process takes a lock in the run() function in
nspawn.c and holds it for the entire runtime of that function. If we
call `machinectl terminate` the machine gets unregistered _before_ we
release the lock, so the original `machinectl status` check would return
early, allowing for a race where we call io.systemd.MachineImage.List
over Varlink when systemd-nspawn still holds the lock because the
process is still running.:

[   41.691826] TEST-13-NSPAWN.sh[1102]: + machinectl terminate long-running
[   41.695009] systemd-nspawn[2171]: Trying to halt container by sending TERM to container PID 1. Send SIGTERM again to trigger immediate termination.
[   41.698235] systemd-machined[1192]: Machine long-running terminated.
[   41.709520] TEST-13-NSPAWN.sh[1102]: + systemctl kill --signal=KILL systemd-nspawn@long-running.service
[   41.709169] systemd-nspawn[2171]: Failed to unregister machine: No machine 'long-running' known
[   41.720869] TEST-13-NSPAWN.sh[2346]: + varlinkctl --more call /run/systemd/machine/io.systemd.MachineImage io.systemd.MachineImage.List '{}'
[   41.723359] TEST-13-NSPAWN.sh[2347]: + grep long-running
...
[   41.735453] TEST-13-NSPAWN.sh[2352]: + varlinkctl call /run/systemd/machine/io.systemd.MachineImage io.systemd.MachineImage.List '{"name":"long-running", "acquireMetadata": "yes"}'
[   41.736222] TEST-13-NSPAWN.sh[2353]: + grep OSRelease
[   41.739500] TEST-13-NSPAWN.sh[2352]: Method call io.systemd.MachineImage.List() failed: Device or resource busy
[   41.740641] systemd[1]: Received SIGCHLD.
[   41.740670] systemd[1]: Child 2171 (systemd-nspawn) died (code=killed, status=9/KILL)
[   41.740725] systemd[1]: systemd-nspawn@long-running.service: Child 2171 belongs to systemd-nspawn@long-running.service.
[   41.740748] systemd[1]: systemd-nspawn@long-running.service: Main process exited, code=killed, status=9/KILL
[   41.740755] systemd[1]: systemd-nspawn@long-running.service: Will spawn child (service_enter_stop_post): systemd-nspawn
[   41.740872] systemd[1]: systemd-nspawn@long-running.service: About to execute: systemd-nspawn --cleanup --machine=long-running
...

Let's mitigate this by waiting until the corresponding
systemd-nspawn@.service instance enters the 'inactive' state where the
lock should be properly released.

Resolves: #39547
(cherry picked from commit ed4903660c90e862c7834ea39772b887b88f8982)
2025-11-06 23:38:13 +00:00
Frantisek Sumsal
9c8e3e54cf test: terminate the test containers cleanly on SIGTERM
So they exit with 0 instead of 143 when we call `machinectl terminate`
on them.

(cherry picked from commit 79a93bb7f52ce71b9d5027e640f59c0f08fbbbcc)
2025-11-06 23:38:13 +00:00
Yu Watanabe
f748583e3d test-network: disable several more sandbox features when running with sanitizers
These settings also imply seccomp.
Hopefully fixes #39567.

(cherry picked from commit 454ce423050890bdc8c3c90add3713592a3cab38)
2025-11-06 23:38:13 +00:00
Yu Watanabe
2a998ced94 test-network: read default values from environment variables
Nowadays, the test script is run as a service, and no argument about
sanitizers are passed. Let's read them from the environment variables.

(cherry picked from commit da665b708a5fb734c3114089f2f58783644b7f6f)
2025-11-06 23:38:13 +00:00
Luca Boccassi
9d485e0223 test: stop piping post-test journalctl commands to /failed
We can't see what the actual issues are when tests fail at that point, eg:

https://github.com/systemd/systemd/actions/runs/19034752357/job/54356278052
(cherry picked from commit 22311a12912509dd8f275b4f5d42383ee70327eb)
2025-11-06 23:38:13 +00:00
Lennart Poettering
9e010a8066 ci: never go to raw tpm device, always go via resource manager
(cherry picked from commit a9d02df0c7b25e11fce74756009014185bbc3377)
2025-11-06 23:38:13 +00:00
Daan De Meyer
84f817f754 TEST-87-AUX-UTILS-VM: Propagate SYSTEMD_PAGER at one more place
(cherry picked from commit cfabf3eb3b27f26175b54bbc562003404e80fa1e)
2025-11-06 23:38:13 +00:00
Frantisek Sumsal
f48447bfa8 test: properly wait for the forked process
The process forked off by `systemd-notify --fork` is not a child of the
current shell, so using `wait` doesn't work. This then later causes a
race, when the test occasionally fails because it attempts to start a
new systemd-socket-activate instance before the old one is completely
gone:

[ 1488.947744] TEST-74-AUX-UTILS.sh[1938]: Child 1947 died with code 0
[ 1488.947952] TEST-74-AUX-UTILS.sh[1933]: + assert_eq hello hello
[ 1488.949716] TEST-74-AUX-UTILS.sh[1948]: + set +ex
[ 1488.950112] TEST-74-AUX-UTILS.sh[1950]: ++ cat /proc/1938/comm
[ 1488.945555] systemd[1]: Started systemd-networkd.service - Network Management.
[ 1488.950365] TEST-74-AUX-UTILS.sh[1933]: + assert_in systemd-socket systemd-socket-
[ 1488.950563] TEST-74-AUX-UTILS.sh[1951]: + set +ex
[ 1488.950766] TEST-74-AUX-UTILS.sh[1933]: + kill 1938
[ 1488.950766] TEST-74-AUX-UTILS.sh[1933]: + wait 1938
[ 1488.950766] TEST-74-AUX-UTILS.sh[1933]: .//usr/lib/systemd/tests/testdata/units/TEST-74-AUX-UTILS.socket-activate.sh: line 14: wait: pid 1938 is not a child of this shell
[ 1488.950766] TEST-74-AUX-UTILS.sh[1933]: + :
[ 1488.951486] TEST-74-AUX-UTILS.sh[1952]: ++ systemd-notify --fork -- systemd-socket-activate -l 1234 --now socat ACCEPT-FD:3 PIPE
[ 1488.952222] TEST-74-AUX-UTILS.sh[1953]: Failed to listen on [::]🔢 Address already in use
[ 1488.952222] TEST-74-AUX-UTILS.sh[1953]: Failed to open '1234': Address already in use
[ 1488.956831] TEST-74-AUX-UTILS.sh[1933]: + PID=1953
[ 1488.957078] TEST-74-AUX-UTILS.sh[102]: + echo 'Subtest /usr/lib/systemd/tests/testdata/units/TEST-74-AUX-UTILS.socket-activate.sh failed'
[ 1488.957078] TEST-74-AUX-UTILS.sh[102]: Subtest /usr/lib/systemd/tests/testdata/units/TEST-74-AUX-UTILS.socket-activate.sh failed

(cherry picked from commit c05758663b162c64da4729944023dec8cf684c75)
2025-11-06 23:38:13 +00:00
Yu Watanabe
279a13734d TEST-75-RESOLVED: stop socket units before stopping the main service
Fixes the following warning:
TEST-75-RESOLVED.sh[2251]: ++ restart_resolved
TEST-75-RESOLVED.sh[2251]: ++ systemctl stop systemd-resolved.service
TEST-75-RESOLVED.sh[2271]: Stopping 'systemd-resolved.service', but its triggering units are still active:
TEST-75-RESOLVED.sh[2271]: systemd-resolved-monitor.socket, systemd-resolved-varlink.socket

(cherry picked from commit f88f0271f84f11643fa20198e2346a2ec4e629ed)
2025-11-06 23:38:13 +00:00
Frantisek Sumsal
163eaa210c test: wait for signed.test's zone DS records to get pushed to the parent zone
It looks like the 4 second sleep might not be enough on some slower
machines (like the ARM GH Actions nodes) which can lead to the DS RRs
propagation to clash with the manual test zone edit, and the
signed.test zone then might end up not properly signed:

TEST-75-RESOLVED.sh[749]: + : '--- ZONE: signed.test (static DNSSEC) ---'
TEST-75-RESOLVED.sh[749]: + run_delv @ns1.unsigned.test signed.test
TEST-75-RESOLVED.sh[749]: + run delv -a /etc/bind.keys @ns1.unsigned.test signed.test
TEST-75-RESOLVED.sh[778]: + delv -a /etc/bind.keys @ns1.unsigned.test signed.test
TEST-75-RESOLVED.sh[779]: + tee /tmp/tmp.2KOIiyrgth
TEST-75-RESOLVED.sh[779]: ;; /etc/bind.keys:1: option 'managed-keys' is deprecated
TEST-75-RESOLVED.sh[779]: ;; validating signed.test/DS: no valid signature found
TEST-75-RESOLVED.sh[779]: ;; validating signed.test/A: no valid signature found
TEST-75-RESOLVED.sh[779]: ; unsigned answer
TEST-75-RESOLVED.sh[779]: signed.test.		86400	IN	A	10.0.0.10
TEST-75-RESOLVED.sh[779]: signed.test.		86400	IN	RRSIG	A 13 2 86400 20251028114356 20251014101356 39330 signed.test. oo3ca8WPusbBPRhzsEKw3bsBBqFtI8i4bckoMVNzt7lY+udGW6PlaSYj OjpQGgY9oglowVM9bteNtwJKHUbvtw==
TEST-75-RESOLVED.sh[749]: + grep -qF '; fully validated' /tmp/tmp.2KOIiyrgth
[FAILED] Failed to start TEST-75-RESOLVED.service - TEST-75-RESOLVED.

Let's explicitly wait for the DS records propagation to finish before we
start editing the test zone to avoid this.

I'm still not completely sure if this is the root cause, but it's the
best shot I currently have, so I'll let the CIs decide.

(cherry picked from commit 92631f1962b1bbd253e5d56a4290ab82805dc43a)
2025-11-06 23:38:13 +00:00
Luca Boccassi
af972669db test: sign extension images used by TEST-50-DISSECT
(cherry picked from commit c581bc8ad810a7e84952791ec644c569c30bbc56)
2025-11-06 23:38:13 +00:00
Antonio Alvarez Feijoo
8b0239e196 test: enable TEST-06-SELINUX in openSUSE
openSUSE switched to SELinux by default for quite some time now, so this test is
also successful.

(cherry picked from commit 2fbfbfc5fad59031d0351e600c058b3ad218c338)
2025-11-06 23:38:13 +00:00
Luca Boccassi
d6c5f1d099 test: call bash with -o pipefail when piping commands in TEST-50-DISSECT
We want the tests to fail if one of the intermediate commands fails,
otherwise it is hard to spot failures

(cherry picked from commit 0ce88a9132c5f653f50246a0cf1aa274ca2c0c62)
2025-11-06 23:38:13 +00:00
Luca Boccassi
524b071a6a test: also test verity signatures on debian testing/unstable
debian testing/unstable do not set VERSION_ID, so if missing, assume
it's testing/unstable which are new enough

(cherry picked from commit dc88805d16f9ca28deb061322bcab1bc52e5f0a0)
2025-11-06 23:38:13 +00:00
Luca Boccassi
27ed3f4c2e test: move checks around in TEST-50-DISSECT so that they can be used from multiple subtests
Also set it up so that unprivileged tests can be done

(cherry picked from commit e8d1a26d9c0920c4d190629e239d94e0edcf11a1)
2025-11-06 23:38:13 +00:00
jouyouyun
d9789b2296 nss-myhostname: use FAMILY_ADDRESS_SIZE instead of the integer 16 when copying ip addr
To avoid copying extra characters when using IPv4.

(cherry picked from commit 05b880ac46b27c65de09d7add6b0e2f5ac3bcd9a)
2025-11-06 21:26:42 +00:00
Chris Down
d5f5ff3ff0 core: Only apply unprivileged userns logic to user managers
Commit 38748596f078 ("core: Make DelegateNamespaces= work for user
managers with CAP_SYS_ADMIN") refactored the logic for when an
unprivileged process should create a new user namespace for sandboxing.

This refactor inadvertently removed a check (`params->runtime_scope !=
RUNTIME_SCOPE_USER`) that differentiated between system services and user
services.

This causes a regression in rootless containers where systemd runs
unprivileged. When starting a system service (like `dbus-broker`) that
uses sandboxing features (eg. with `PrivateTmp=yes`), systemd now
incorrectly creates a new, minimal `PRIVATE_USERS_SELF` namespace.

This new namespace only maps UID/GID 0. When dbus-broker attempts to
drop privileges to the `dbus` user (GID 81), the `setresgid(81, 81, 81)`
call fails because GID 81 is not mapped.

Restore the check to ensure that the special unprivileged sandboxing
logic is only applied to user services, as was the original intent.
System services in a rootless context will now correctly run in the
container's main user namespace, where all necessary UIDs/GIDs are
mapped.

Fixes: https://github.com/systemd/systemd/issues/39563
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2391343
(cherry picked from commit 666cd35be493e2d796c5424eed9a3deeddc9b0fe)
2025-11-06 21:26:42 +00:00
Mike Yuan
067674fd02 TEST-74-AUX-UTILS.run: add test case for #39038
(cherry picked from commit 7400e375786ab45c2c350b7eb6e1209ab54df802)
2025-11-06 21:26:42 +00:00
Mike Yuan
2c78b439c7 core/exec-invoke: gracefully handle lack of privilege for initgroups() in user mode
Otherwise specifying User=SELF also fails because we got
no privilege to call setgroups().

Fixes #39038

(cherry picked from commit c86914667a4ad1debea0cb0cab44df3f10b36dbf)
2025-11-06 21:26:42 +00:00
Kai Lueke
5541e2df06 sysext: Check for /etc/initrd-release in given --root= tree
Both sysext and confext used the host's /etc/initrd-release file even
when --root=/somewhere was specified. A workaround was the
SYSTEMD_IN_INITRD= env var but without knowing this it was quite
confusing. Aside from users validating their extensions, the primary
use case for this to matter is when the extensions are set up from the
initrd where the initrd-release file is present when running but we want
to prepare the extensions for the final system and thus should match
for the right scope.
Make systemd-sysext check for /etc/initrd-release inside the given
--root= tree. An alternative would be to always ignore the
initrd-release check when --root= is passed but this way it is more
consistent. The image policy logic for EFI-loader-passed extensions
won't take effect when --root= is used, though.

(cherry picked from commit 570eae5007cbf2852f7c314f80224ecf3c828b25)
2025-11-06 21:26:42 +00:00
Kai Lueke
1d696f8ced test: Add missing test cleanup for the last sysext test
The last sysext test leaked things into new tests added later,
uncovered by any new tests leftover check.
Remove the mutable folder state through a trap as done in other tests.

(cherry picked from commit 6649562924f361edca98ce3d015bd7dcda97b076)
2025-11-06 21:26:42 +00:00
jouyouyun
fd38588cea cgls: print error messages when --unit and --user-unit are used together
Mixing the `--unit` and `--user-unit` options will result in error messages.
During the parsing phase, only the `arg_show_unit` record of the last
occurrence of the option is used; all names are placed in the same `arg_names`,
thus mixing the two types of units in the query.

For example, `-u foo --user-unit bar` will also treat `foo` as a user unit and
query it in the user service.

(cherry picked from commit 2b8c7adbecb929f131dc05d8b88babd87cc0ab22)
2025-11-06 21:26:42 +00:00
Chris Down
b64317021a systemctl: Fix shutdown time parsing across DST changes
When parsing an absolute time specification like `hh:mm` for the
`shutdown` command, the code interprets a time in the past as "tomorrow
at this time". It currently implements this by adding a fixed 24-hour
duration (`USEC_PER_DAY`) to the timestamp.

This assumption breaks across DST transitions, as the day might not be
24 hours long. This can cause the shutdown to be scheduled at the wrong
time (typically off by one hour in either direction).

Change the logic to perform calendar arithmetic instead of timestamp
arithmetic. If the calculated time is in the past, we increment
`tm.tm_mday` and call `mktime_or_timegm_usec()` a second time.

This delegates all date normalization logic to `mktime()`, which
correctly handles all edge cases, including DST transitions, month-end
rollovers, and leap years.

Fixes: https://github.com/systemd/systemd/issues/39232
(cherry picked from commit a8c3ac66721de23cceff359d946ecd9695bbacb8)
2025-11-06 21:26:42 +00:00
Zbigniew Jędrzejewski-Szmek
433d4fca37 systemctl: downgrade or silence warnings for --now
When calling systemctl enable/disable/reenable --now, we'd always fail with
error when operating offline. This seemly overly restricitive. In particular,
if systemd is not running at all, the service is not running either, so
complaining that we can't stop it is completely unnecessary. But even when
operating in a chroot where systemd is not running, let's just emit a warning
and return success. It's fairly common to have installation or package scripts
which do such calls and not starting/restarting the service in those scenarios
is the desired and expected operation. (If --now is called in combination
with --global or --root=, keep returning an error.)

Also make the messages nicer. I was adding some docs to tell the user to run
'systemctl enable --now', and checked how the command can fail, and the error
message that the user might see in some common scenarios was too complicated.
Split it up to be nicer.

(cherry picked from commit 77a1cc8fa09c264991d147ec71d70a4b5d2a553e)
2025-11-06 21:26:42 +00:00
Zbigniew Jędrzejewski-Szmek
7e43380e98 systemctl: convert return value of install_client_side() to enum
The checks are reordered to do checks that don't require interacting with the
system first.

(cherry picked from commit 0ff5985176acaccf4d2f220f92e14cd0f6ee82bf)
2025-11-06 21:26:42 +00:00
Daan De Meyer
20fd371151 TEST-65-ANALYZE: Add missing --no-pager
(cherry picked from commit da30f59f602c61dc3219d4d7bfea1cccfcc7a139)
2025-11-06 21:26:42 +00:00
Lennart Poettering
c5567d6ba1 homed: always report that registered users are members of their own groups
As per the userdb spec we should report in GetMemberships() that users
are in their own groups. Hence follow the spec.

Fixes: #26061
(cherry picked from commit 9851382c124dc81bad559c7bd0a86e8ff37f82ab)
2025-11-06 21:26:42 +00:00
Lennart Poettering
3b882d6806 rm-rf: make sure we can safely remove dirs we have no access to via rm_rf_at()
Previously, we'd first empty a dir, and then remove it. This works fine
as long as we have access to a dir. But in some cases (like for example
a foreign owned container tree) we might not have access to the dir, but
are still able to remove it (because it is empty, and in a dir we own).
Hence let's try that first. If it works, we do not need to enter the dir
(and thus fail).

(cherry picked from commit 502f7a2b804370d32adb373e661831f583565075)
2025-11-06 21:26:42 +00:00
Luca Boccassi
0483ee5dd9 sd-varlink: when expecting a type and refusing due to mismatch say what was received
Sometimes it is not obvious why a message is not accepted,
so explicitly say what type was received in the log message

(cherry picked from commit d08b2f2a06da445e15f3eb007e3b348e1cd71923)
2025-11-06 21:26:42 +00:00
Lennart Poettering
1a12193be0 rules: apply loopback block device rule only onto loopback block devices
Fixes: #39426
Follow-up for: 9422ce83c201ab4154de832331f0b351fc5137f6

(cherry picked from commit 6fac8bb9b1f42bd08236dfc53cf8c37e66a72212)
2025-11-06 21:26:42 +00:00
Michal Sekletar
711109fef3 coredump: handle ENOBUFS and EMSGSIZE the same way
Depending on the runtime configuration, e.g. sysctls
net.core.wmem_default= and net.core.rmem_default and on the actual
message size, sendmsg() can fail also with ENOBUFS. E.g. alloc_skb()
failure caused by net.core.[rw]mem_default=64MiB and huge fdinfo list
from process that has 90k opened FDs.

We should handle this case in the same way as EMSGSIZE and drop part of
the message.

(cherry picked from commit 28e62e684b631f928f1d857b04f45f0d34441675)
2025-11-06 21:26:42 +00:00
Daan De Meyer
3f04968391 rpm: Make sure we only match files in the directories in triggers
/usr/lib/systemd/system will match /usr/lib/systemd/systemd-networkd,
which is definitely not the intention.

(cherry picked from commit 1835ce2f045815f70849c29426c0c9c0f1a5af9c)
2025-11-06 21:26:42 +00:00
DaanDeMeyer
ac54da0718 machine-bind-user: Use machine in log messages instead of container
(cherry picked from commit 9aa6c30bbdd43f62a322516f82ba9ac1780a492b)
2025-11-06 21:26:42 +00:00
Daan De Meyer
5e989c5ad6 nspawn: Add --bind-user-shell= to --help
(cherry picked from commit 64d5bb4d53a5d002b15d9ff6aa1a0a09597e2074)
2025-11-06 21:26:42 +00:00
theSillywhat
1a2d944614 Missing policies for polkit as mentioned in freedesktop.org/software/systemd/man
(cherry picked from commit 3331d99b491fd334a0695064fcbd19b651016c51)
2025-11-06 21:26:42 +00:00
Zbigniew Jędrzejewski-Szmek
9c1db4cd8e Do not use "critical assert_return" in libsystemd or libudev
Previously, when compiled in developer mode, a call into libsystemd with
invalid parameters would result in an abort. This means that it's effectively
impossible to install such libsystemd in a normal system, since various
third-party programs may now abort. A shared library should generally never
abort or exit the calling program.

In python-systemd, the test suite calls into libsystemd, to check if the proper
return values are received and propagated through the Python wrappers.
Obviously with libsystemd compiled from git, the test suite now fails
in a nasty way.

So rework the code to set assert_return_is_critical similarly to how we handle
mempool enablement: the function that returns true is declared as a week
symbol, and we "opt in" by linking a file that provides the function in
libsystemd-shared. Effectively, libsystemd and libudev always have
assert_return_is_critical==false, and our binaries and modules enable it
conditionally.

(cherry picked from commit 0bb0316f5eb2c8d30e91feac571404687c6a0dc2)
2025-11-06 21:26:42 +00:00
Zbigniew Jędrzejewski-Szmek
29cbe93ea5 basic/mempool: mark mempool_enabled as _pure_
The function internally does caching which means that the result must
always be the same, the definition of a pure function. The compiler might
be able to optimize some repeated calls to the function.

(cherry picked from commit 882dfbde1c3159689eabadfab430aa9c272af163)
2025-11-06 21:26:42 +00:00
Septatrix
3ad1fced57 Remove dns0.eu from default DNS servers
The service has ceased operation.
Partially reverts 02527e95b55f3f970d29d3001269311c60f6717c.

(cherry picked from commit 93b6d432535d954793360e211802ecb2139c6ce1)
2025-11-06 21:26:42 +00:00
Lennart Poettering
90133eace3 units: use Title Case for network generator description string
We use Title Case for all other units, do so here too.

(cherry picked from commit 15fec4b6464304dd4abaaea4088b0228c4dfdf6c)
2025-11-06 21:26:42 +00:00
Yu Watanabe
695fb59075 coredumpctl: fix condition for checking coredump journal entry
If one of PID, UID, GID, or SIGNAL is missing, then parse_uid() and
friends in the below will trigger assertion. This fixes that.

Also, only PID, UID, GID, SIGNAL, and COMM are mandatory fields, but
others are not, hence this drops others from the condition.

Moreover, this mekes 'coredumpctl --list' not fail even if there exists a
broken coredump entry in journal.

(cherry picked from commit 94a23e9c440962634e28b52babcb2b8aadd6ae96)
2025-11-06 21:26:42 +00:00
Peter Hutterer
9098d3d7f9 hwdb: don't tag a named Mouse device as pointingstick
The generic kernel hid drivers split up devices based on the application
collection, appending a suffix for each collection (e.g. Touchpad,
Mouse, ...). Many i2c touchpads get a "... Mouse" event node which is
mislabelled as pointingstick by the input_id builtin, see commit
3d7ac1c655ec40f3829543072494dcdfb92dbc6b.

Closes: https://github.com/systemd/systemd/issues/36677
(cherry picked from commit c4f072aaadedd9029bf0bef2036fdab8a4a3c180)
2025-11-06 21:26:42 +00:00
Peter Hutterer
4a8df48f20 rules: extend 60-input-id.rules to allow for bus/vid/pid/name matches
Same approach as used in 70-mouse.rules, allow for a name-based match
optionally combined with bus/vid/pid (which the existing modalias rule
would already allow us anyway). Note that ID_BUS isn't assigned until
after this rule has run so we need to use the id/bustype attribute
directly.

Related to https://github.com/systemd/systemd/issues/36677

(cherry picked from commit 5b647b84a935abd57ff7aaa61d3a64c5c6ffd0db)
2025-11-06 21:26:42 +00:00
Luca Boccassi
b80d4387fa bpf: do not leak dlopen object
CID#1609833

(cherry picked from commit 8112069be0aed99cc56777800481303d4f613550)
2025-11-06 21:26:42 +00:00
Luca Boccassi
886f288db1 efivars: fix potential memory leak
If 'ret' is not passed, 'x' is leaked

Follow-up for c8d60ae79d1763c6ef16fdb306b65d909a769de8

CID#1621673

(cherry picked from commit 05d45875f74cfb7455d127a5229dca440986e689)
2025-11-06 21:26:42 +00:00
Luca Boccassi
ba87dcfe69 dissect: drop leftover assert
This was refactored, and the assert is now wrongly placed. Drop
it to fix coverity warning.

Follow-up for dfdeb0b1cbb05a213f0965eedfe0e7ef06cd39d3

CID#1639975

(cherry picked from commit d2754100864d6de14a4758bfea5d8e4401120c69)
2025-11-06 21:26:42 +00:00
Mike Yuan
21389c1e22 core/mount: properly handle REMOUNTING_* states in mount_stop()
Currently, mount_stop() simply turns REMOUNTING_* into corresponding
UNMOUNTING_* states. However the transition is bogus, because
the interruption of remount does not bring down the mount.
Let's instead follow the logic of service_stop(), i.e. terminate
the remount process and spawn umount.

(cherry picked from commit 6ebb91d92fb5ea7d43b22bec1b76cde1230b0e12)
2025-11-06 21:26:42 +00:00
Mike Yuan
aabcc77c54 core/mount: remove one more unused temporary variable
Similar to 3cea9c403c6d5ff0edb2b8fc99884f2243b1456e,
but for mount_get_what_escaped().

(cherry picked from commit a8fe8e83447a39831a23d82a82614fc19f2b9b46)
2025-11-06 21:26:42 +00:00
Daan De Meyer
a70f9c7c68 core: Don't use TTYPath= for PAM unless StandardInput=tty
Fixes #39334

(cherry picked from commit f875a8026ec2dfa6026da3ee216782e9f7c04a43)
2025-11-06 21:26:42 +00:00
Yu Watanabe
e64a0ffd03 nsresource: fix varlink method dispatch table
Follow-up for 716bf93c4bde07c1870b9b0837f2ec33f36686f1 (v258).

(cherry picked from commit 0d87de0b8ed77f05c3f60dbee7b801cf3dd5f647)
2025-11-06 21:26:42 +00:00
Frantisek Sumsal
7de1f51c7c timer: rebase the next elapse timestamp only if timer didn't already run
The test added in f4c3c107d9be4e922a080fc292ed3889c4e0f4a5 uncovered a
corner case while recalculating the next elapse timestamp of a timer unit
that uses RandomizedDelaySec= during deserialization.

If the scheduled time (without RandomizedDelaySec=) already elapsed,
systemd "rebases" the next elapse timestamp to the time when systemd
first started, to make the RandomizedDelaySec= feature work even at
boot. However, since it was done unconditionally, it always overrode the
next elapse timestamp, which could then cause the final next elapse
timestamp to fall out of the expected window.

With a couple of additional debug logs one of the test fail looks like
this:

[  132.129815] TEST-53-TIMER.sh[384]: + : 'Next elapse timestamp after daemon-reload, try #328'
[  132.129815] TEST-53-TIMER.sh[384]: + systemctl daemon-reload
[  132.136352] systemd[1]: Reload requested from client PID 16399 ('systemctl') (unit TEST-53-TIMER.service)...
[  132.136636] systemd[1]: Reloading...
[  132.446160] systemd[1]: Rebasing next elapse timestamp
[  132.446168] systemd[1]: v->next_elapse: Tue 2025-10-14 00:10:00 CEST
[  132.446170] systemd[1]: rebased: Tue 2025-10-14 00:10:56 CEST
[  132.446172] systemd[1]: v->next_elapse after rebase: Tue 2025-10-14 00:10:56 CEST
[  132.447361] systemd[1]: Reloading finished in 310 ms.
[  132.484041] TEST-53-TIMER.sh[384]: + check_elapse_timestamp
[  132.484041] TEST-53-TIMER.sh[384]: + systemctl status timer-RandomizedDelaySec-16377.timer
[  132.533657] TEST-53-TIMER.sh[16440]: ● timer-RandomizedDelaySec-16377.timer
[  132.533657] TEST-53-TIMER.sh[16440]:      Loaded: loaded (/run/systemd/system/timer-RandomizedDelaySec-16377.timer; static)
[  132.533657] TEST-53-TIMER.sh[16440]:      Active: active (waiting) since Mon 2025-10-13 23:00:00 CEST; 1h 13min ago
[  132.533657] TEST-53-TIMER.sh[16440]:  Invocation: 5555d4f060114a5493ff228013830d17
[  132.533657] TEST-53-TIMER.sh[16440]:     Trigger: Tue 2025-10-14 22:10:04 CEST; 21h left
[  132.533657] TEST-53-TIMER.sh[16440]:    Triggers: ● timer-RandomizedDelaySec-16377.service
[  132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:07 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Changed dead -> waiting
[  132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:07 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Adding 15h 35min 1.230173s random time.
[  132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:07 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Realtime timer elapses at Tue 2025-10-14 15:45:58 CEST.
[  132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:07 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Changed dead -> waiting
[  132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Adding 16h 29min 44.084409s random time.
[  132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Realtime timer elapses at Tue 2025-10-14 16:40:41 CEST.
[  132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Changed dead -> waiting
[  132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Adding 21h 59min 7.955828s random time.
[  132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Realtime timer elapses at Tue 2025-10-14 22:10:04 CEST.
[  132.533657] TEST-53-TIMER.sh[16440]: Oct 14 00:13:08 H systemd[1]: timer-RandomizedDelaySec-16377.timer: Changed dead -> waiting
[  132.535386] TEST-53-TIMER.sh[384]: + systemctl show -p InactiveExitTimestamp timer-RandomizedDelaySec-16377.timer
[  132.537727] TEST-53-TIMER.sh[16442]: InactiveExitTimestamp=Mon 2025-10-13 23:00:00 CEST
[  132.540317] TEST-53-TIMER.sh[16444]: ++ systemctl show -P NextElapseUSecRealtime timer-RandomizedDelaySec-16377.timer
[  132.547745] TEST-53-TIMER.sh[384]: + NEXT_ELAPSE_REALTIME='Tue 2025-10-14 22:10:04 CEST'
[  132.548020] TEST-53-TIMER.sh[16445]: ++ date '--date=Tue 2025-10-14 22:10:04 CEST' +%s
[  132.550218] TEST-53-TIMER.sh[384]: + NEXT_ELAPSE_REALTIME_S=1760472604
[  132.550218] TEST-53-TIMER.sh[384]: + : 'Next elapse timestamp should be Tue 2025-10-14 00:10:00 CEST <= Tue 2025-10-14 22:10:04 CEST <= Tue 2025-10-14 22:10:00 CEST'
[  132.550218] TEST-53-TIMER.sh[384]: + assert_ge 1760472604 1760393400
[  132.550555] TEST-53-TIMER.sh[16446]: + set +ex
[  132.550702] TEST-53-TIMER.sh[384]: + assert_le 1760472604 1760472600
[  132.550832] TEST-53-TIMER.sh[16447]: + set +ex
[  132.551091] TEST-53-TIMER.sh[16447]: FAIL: '1760472604' > '1760472600'

Here the original next elapse timestamp was Tue 2025-10-14 00:10:00 CEST
as expected, but it was overridden by the rebased timestamp:
Tue 2025-10-14 00:10:56 CEST. And when a new randomized delay was added
to it (21h 59min 7.955828s) the final next elapse timestamp fell out of
the expected window, i.e. Tue 2025-10-14 00:10:00 (scheduled time) <
Tue 2025-10-14 22:10:04 CEST (rebased elapse timestamp + randomized
delay) < Tue 2025-10-14 22:10:00 CEST (scheduled time + maximum from
RandomizedDelaySec=, i.e. 22h).

By limiting the timestamp rebase only the case where the unit hasn't
already run should prevent this from happening during daemon-reload.

(cherry picked from commit bdb8e584f4509de0daebbe2357d23156160c3a90)
2025-11-06 21:26:42 +00:00
Frantisek Sumsal
77f88042e6 test: format the min/max timestamps in "systemd" style
Before:
  Next elapse timestamp should be Sun Oct 12 00:10:00 UTC 2025 <= Sun 2025-10-12 05:43:04 UTC <= Sun Oct 12 22:10:00 UTC

After:
  Next elapse timestamp should be Tue 2025-10-14 00:10:00 CEST <= Tue 2025-10-14 19:39:11 CEST <= Tue 2025-10-14 22:10:00 CEST
(cherry picked from commit 62ca845ac776d5877fe46dab52692053df6c8efa)
2025-11-06 21:26:42 +00:00
Zbigniew Jędrzejewski-Szmek
76a686b648 core: allow split /usr/local/s?sbin with merged /usr/s?bin
Previously, we used either the fully split path or the fully merged path,
treating "split sbin" as a boolean condition. The idea was that conversion to
to merged bin would be a single event, so we don't need to care about the
details of the transition. But it turns out that some systems may be converted
in disparate steps. In https://bugzilla.redhat.com/show_bug.cgi?id=2400220,
there was a lengthy discussion about a coreos system where
/usr/local/{bin,sbin} were created as separate directories. Since /usr/local is
not part of the packaged system, it might remain split for a longer time. So
check /usr/local/s?bin separately and stop adding /usr/sbin to $PATH if only
/usr/local/s?bin is split. (I don't think it makes sense to handle the reverse
case, i.e. only /usr/s?bin being split, since that should be much rarer.)

Inspired by https://bugzilla.redhat.com/show_bug.cgi?id=2400220.

(cherry picked from commit e63917abe16c37c828f99710f1e9922093d9a2b9)
2025-11-06 21:26:42 +00:00
Mike Yuan
5179e7a558 core/service: properly handle freezer action -> watchdog propagation
Follow-up for 25178aadb2bd04ef9e63f48c1ef42fb309f9332e

(cherry picked from commit 4f07ec2b651e40fe04455e660606d2a0f9ae375c)
2025-11-06 21:26:42 +00:00
Mike Yuan
af954efb16 core/service: drop "cgroup" part of service_cgroup_freezer_action()
This operates on more than cgroup, hence use generic naming,
which also aligns with slice_freezer_action().

(cherry picked from commit b5381d76d591a3cf428bc1a5f3e187dccaf5ea2e)
2025-11-06 21:26:42 +00:00
Mike Yuan
e155b83d3f unit-def: introduce freezer_state_objective()
No functional change, preparation for later commits.

(cherry picked from commit 1cbbb05bc76015bb6f48c217453e98a73cc30344)
2025-11-06 21:26:42 +00:00
81 changed files with 632 additions and 343 deletions

View File

@ -137,7 +137,7 @@ jobs:
sanitizers: ""
llvm: 0
cflags: "-Og"
relabel: no
relabel: yes
vm: 0
no_qemu: 0
no_kvm: 0

View File

@ -63,8 +63,11 @@ NTP servers.
## DNS Servers
By default, systemd-resolved uses Cloudflare, Google, Quad9 and DNS0 Public DNS servers
`1.1.1.1`, `8.8.8.8`, `9.9.9.9`, `193.110.81.0`, `1.0.0.1`, `8.8.4.4`, `149.112.112.112`, `185.253.5.0`, `2606:4700:4700::1111`, `2001:4860:4860::8888`, `2620:fe::fe`, `2a0f:fc80::`, `2606:4700:4700::1001`, `2001:4860:4860::8844`, `2620:fe::9`, `2a0f:fc81::`
By default, systemd-resolved uses Cloudflare, Google and Quad9 Public DNS servers
`1.1.1.1`, `8.8.8.8`, `9.9.9.9`,
`1.0.0.1`, `8.8.4.4`, `149.112.112.112`,
`2606:4700:4700::1111`, `2001:4860:4860::8888`, `2620:fe::fe`,
`2606:4700:4700::1001`, `2001:4860:4860::8844`, `2620:fe::9`
as fallback, if no other DNS configuration is available.
Use `-Ddns-servers=` to direct systemd-resolved to different fallback

View File

@ -5,6 +5,7 @@
#
# Match string formats:
# id-input:modalias:<modalias>
# id-input:<bus>:v<vid>p<pid>:name:<name>:*
#
# To add local entries, create a new file
# /etc/udev/hwdb.d/61-input-id-local.hwdb
@ -47,9 +48,20 @@
# id-input:modalias:input:b0003v1234pABCD*
# ID_INPUT_TOUCHPAD=1
# ID_INPUT=1
#
# id-input:usb:v12abp34cd:name:SomeVendor *:*
# ID_INPUT_TOUCHPAD=1
# ID_INPUT=1
#
# For technical reasons the hexadecimal vid/pid in the modalias match are
# uppercase but lowercase in the bus/vid/pid/name match.
# Sort by brand, model
# Any i2c device with a Mouse suffix in the name is not a pointing stick
id-input:i2c:*:name:*Mouse:
ID_INPUT_POINTINGSTICK=0
# Code Mercenaries Hard- und Software GmbH Virtual RC USB
id-input:modalias:input:b0003v07C0p1125*
ID_INPUT_MOUSE=

View File

@ -75,7 +75,7 @@ UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_')
TYPES = {'mouse': ('usb', 'bluetooth', 'ps2', '*'),
'evdev': ('name', 'atkbd', 'input'),
'fb': ('pci', 'vmbus'),
'id-input': ('modalias'),
'id-input': ('modalias', 'bluetooth', 'i2c', 'usb'),
'touchpad': ('i8042', 'rmi', 'bluetooth', 'usb'),
'joystick': ('i8042', 'rmi', 'bluetooth', 'usb'),
'keyboard': ('name', ),

View File

@ -83,7 +83,7 @@
<para>Capsule names may be chosen freely by the user, however, they must be suitable as UNIX filenames
(i.e. 255 characters max, and contain no <literal>/</literal>), and when prefixed with
<literal>p-</literal> be suitable as a user name matching strict POSIX rules, see <ulink
<literal>c-</literal> be suitable as a user name matching strict POSIX rules, see <ulink
url="https://systemd.io/USER_NAMES">User/Group Name Syntax</ulink> for details.</para>
<xi:include href="version-info.xml" xpointer="v256"/>

View File

@ -346,7 +346,6 @@ $ ukify build \
<programlisting># systemd-cryptenroll --tpm2-device=auto \
--tpm2-public-key=tpm2-pcr-public-key.pem \
--tpm2-signature=tpm2-pcr-signature.json \
--tpm2-pcrs="" \
/dev/sda5</programlisting>
<para>And then unlock the device with the signature:</para>

View File

@ -4351,7 +4351,7 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
</row>
<row>
<entry><literal>exec-condition</literal></entry>
<entry>Service did not run because <varname>ExecCondition=</varname> failed.</entry>
<entry>Service did not run because <varname>ExecCondition=</varname> failed (that is its command exited with an exit status of 1 through 254 (inclusive)).</entry>
</row>
<row>
<entry><literal>oom-kill</literal></entry>

View File

@ -367,7 +367,7 @@ option('dns-over-tls', type : 'combo', choices : ['auto', 'gnutls', 'openssl', '
description : 'DNS-over-TLS support')
option('dns-servers', type : 'string',
description : 'space-separated list of default DNS servers',
value : '1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google 9.9.9.9#dns.quad9.net 193.110.81.0#dns0.eu 1.0.0.1#cloudflare-dns.com 8.8.4.4#dns.google 149.112.112.112#dns.quad9.net 185.253.5.0#dns0.eu 2606:4700:4700::1111#cloudflare-dns.com 2001:4860:4860::8888#dns.google 2620:fe::fe#dns.quad9.net 2a0f:fc80::#dns0.eu 2606:4700:4700::1001#cloudflare-dns.com 2001:4860:4860::8844#dns.google 2620:fe::9#dns.quad9.net 2a0f:fc81::#dns0.eu')
value : '1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google 9.9.9.9#dns.quad9.net 1.0.0.1#cloudflare-dns.com 8.8.4.4#dns.google 149.112.112.112#dns.quad9.net 2606:4700:4700::1111#cloudflare-dns.com 2001:4860:4860::8888#dns.google 2620:fe::fe#dns.quad9.net 2606:4700:4700::1001#cloudflare-dns.com 2001:4860:4860::8844#dns.google 2620:fe::9#dns.quad9.net')
option('ntp-servers', type : 'string',
description : 'space-separated list of default NTP servers',
value : 'time1.google.com time2.google.com time3.google.com time4.google.com')

View File

@ -13,4 +13,4 @@ ACTION!="remove", SUBSYSTEM=="block", \
OPTIONS+="watch"
# Reset access rights to each loopback device once it gets detached.
SUBSYSTEM=="block", ACTION=="change", ENV{DISK_MEDIA_CHANGE}=="1", TEST!="loop/backing_file", GROUP="disk", MODE="660"
ACTION=="change", SUBSYSTEM=="block", KERNEL=="loop*", ENV{DISK_MEDIA_CHANGE}=="1", TEST!="loop/backing_file", GROUP="disk", MODE="660"

View File

@ -5,4 +5,15 @@ ACTION=="remove", GOTO="id_input_end"
SUBSYSTEM=="input", ENV{ID_INPUT}=="", IMPORT{builtin}="input_id"
SUBSYSTEM=="input", IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=id-input:modalias:"
# id-input:<bus>:v<vid>p<pid>:name:<name>:*
KERNELS=="input*", ATTRS{id/bustype}=="0003", \
IMPORT{builtin}="hwdb 'id-input:usb:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
GOTO="id_input_end"
KERNELS=="input*", ATTRS{id/bustype}=="0005", \
IMPORT{builtin}="hwdb 'id-input:bluetooth:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
GOTO="id_input_end"
KERNELS=="input*", ATTRS{id/bustype}=="0018", \
IMPORT{builtin}="hwdb 'id-input:i2c:v$attr{id/vendor}p$attr{id/product}:name:$attr{name}:'", \
GOTO="id_input_end"
LABEL="id_input_end"

View File

@ -4,40 +4,13 @@
#include <stdlib.h>
#include "assert-util.h"
#include "env-util.h"
#include "errno-util.h"
#include "log.h"
static bool assert_return_is_critical = BUILD_MODE_DEVELOPER;
/* Akin to glibc's __abort_msg; which is private and we hence cannot
* use here. */
static char *log_abort_msg = NULL;
void log_set_assert_return_is_critical(bool b) {
assert_return_is_critical = b;
}
void log_set_assert_return_is_critical_from_env(void) {
static int cached = INT_MIN;
int r;
if (cached == INT_MIN) {
r = secure_getenv_bool("SYSTEMD_ASSERT_RETURN_IS_CRITICAL");
if (r < 0 && r != -ENXIO)
log_debug_errno(r, "Failed to parse $SYSTEMD_ASSERT_RETURN_IS_CRITICAL, ignoring: %m");
cached = r;
}
if (cached >= 0)
log_set_assert_return_is_critical(cached);
}
bool log_get_assert_return_is_critical(void) {
return assert_return_is_critical;
}
static void log_assert(
int level,
const char *text,
@ -73,8 +46,8 @@ _noreturn_ void log_assert_failed_unreachable(const char *file, int line, const
}
void log_assert_failed_return(const char *text, const char *file, int line, const char *func) {
if (assert_return_is_critical)
/* log_get_assert_return_is_critical is a weak symbol. It may be NULL. */
if (log_get_assert_return_is_critical && log_get_assert_return_is_critical())
log_assert_failed(text, file, line, func);
PROTECT_ERRNO;

View File

@ -5,9 +5,7 @@
/* Logging for various assertions */
void log_set_assert_return_is_critical(bool b);
void log_set_assert_return_is_critical_from_env(void);
bool log_get_assert_return_is_critical(void) _pure_;
bool log_get_assert_return_is_critical(void) _weak_ _pure_;
void log_assert_failed_return(const char *text, const char *file, int line, const char *func);

View File

@ -164,9 +164,8 @@ int efi_get_variable(
}
int efi_get_variable_string(const char *variable, char **ret) {
_cleanup_free_ void *s = NULL;
_cleanup_free_ void *s = NULL, *x = NULL;
size_t ss = 0;
char *x;
int r;
assert(variable);
@ -180,7 +179,7 @@ int efi_get_variable_string(const char *variable, char **ret) {
return -ENOMEM;
if (ret)
*ret = x;
*ret = TAKE_PTR(x);
return 0;
}

View File

@ -22,6 +22,6 @@ static struct mempool pool_name = { \
.at_least = alloc_at_least, \
}
__attribute__((weak)) bool mempool_enabled(void);
bool mempool_enabled(void) _weak_ _pure_;
void mempool_trim(struct mempool *mp);

View File

@ -1518,30 +1518,40 @@ int path_glob_can_match(const char *pattern, const char *prefix, char **ret) {
return false;
}
const char* default_PATH(void) {
#if HAVE_SPLIT_BIN
static int split = -1;
static bool dir_is_split(const char *a, const char *b) {
int r;
/* Check whether /usr/sbin is not a symlink and return the appropriate $PATH.
* On error fall back to the safe value with both directories as configured */
if (split < 0)
STRV_FOREACH_PAIR(bin, sbin, STRV_MAKE("/usr/bin", "/usr/sbin",
"/usr/local/bin", "/usr/local/sbin")) {
r = inode_same(*bin, *sbin, AT_NO_AUTOMOUNT);
if (r > 0 || r == -ENOENT)
continue;
if (r < 0)
log_debug_errno(r, "Failed to compare \"%s\" and \"%s\", using compat $PATH: %m",
*bin, *sbin);
split = true;
break;
}
if (split < 0)
split = false;
if (split)
return DEFAULT_PATH_WITH_SBIN;
#endif
return DEFAULT_PATH_WITHOUT_SBIN;
r = inode_same(a, b, AT_NO_AUTOMOUNT);
if (r < 0 && r != -ENOENT) {
log_debug_errno(r, "Failed to compare \"%s\" and \"%s\", assuming split directories: %m", a, b);
return true;
}
return r == 0;
}
#endif
const char* default_PATH(void) {
#if HAVE_SPLIT_BIN
static const char *default_path = NULL;
/* Return one of the three sets of paths:
* a) split /usr/s?bin, /usr/local/sbin doesn't matter.
* b) merged /usr/s?bin, /usr/sbin is a symlink, but /usr/local/sbin is not,
* c) fully merged, neither /usr/sbin nor /usr/local/sbin are symlinks,
*
* On error the fallback to the safe value with both directories as configured is returned.
*/
if (default_path)
return default_path;
if (dir_is_split("/usr/sbin", "/usr/bin"))
return (default_path = DEFAULT_PATH_WITH_FULL_SBIN); /* a */
if (dir_is_split("/usr/local/sbin", "/usr/local/bin"))
return (default_path = DEFAULT_PATH_WITH_LOCAL_SBIN); /* b */
return (default_path = DEFAULT_PATH_WITHOUT_SBIN); /* c */
#else
return DEFAULT_PATH_WITHOUT_SBIN;
#endif
}

View File

@ -9,10 +9,11 @@
#define PATH_MERGED_BIN(x) x "bin"
#define PATH_MERGED_BIN_NULSTR(x) x "bin\0"
#define DEFAULT_PATH_WITH_SBIN PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/")
#define DEFAULT_PATH_WITH_FULL_SBIN PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/")
#define DEFAULT_PATH_WITH_LOCAL_SBIN PATH_SPLIT_BIN("/usr/local/") ":" PATH_MERGED_BIN("/usr/")
#define DEFAULT_PATH_WITHOUT_SBIN PATH_MERGED_BIN("/usr/local/") ":" PATH_MERGED_BIN("/usr/")
#define DEFAULT_PATH_COMPAT PATH_SPLIT_BIN("/usr/local/") ":" PATH_SPLIT_BIN("/usr/") ":" PATH_SPLIT_BIN("/")
#define DEFAULT_PATH_COMPAT DEFAULT_PATH_WITH_FULL_SBIN ":" PATH_SPLIT_BIN("/")
const char* default_PATH(void);

View File

@ -144,6 +144,16 @@ FreezerState freezer_state_finish(FreezerState state) {
return freezer_state_finish_table[state];
}
FreezerState freezer_state_objective(FreezerState state) {
FreezerState objective;
objective = freezer_state_finish(state);
if (objective == FREEZER_FROZEN_BY_PARENT)
objective = FREEZER_FROZEN;
return objective;
}
static const char* const unit_marker_table[_UNIT_MARKER_MAX] = {
[UNIT_MARKER_NEEDS_RELOAD] = "needs-reload",
[UNIT_MARKER_NEEDS_RESTART] = "needs-restart",

View File

@ -325,6 +325,7 @@ UnitActiveState unit_active_state_from_string(const char *s) _pure_;
const char* freezer_state_to_string(FreezerState i) _const_;
FreezerState freezer_state_from_string(const char *s) _pure_;
FreezerState freezer_state_finish(FreezerState i) _const_;
FreezerState freezer_state_objective(FreezerState state) _const_;
const char* unit_marker_to_string(UnitMarker m) _const_;
UnitMarker unit_marker_from_string(const char *s) _pure_;

View File

@ -114,12 +114,20 @@ static int parse_argv(int argc, char *argv[]) {
break;
case 'u':
if (arg_show_unit == SHOW_UNIT_USER)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Cannot combine --unit with --user-unit.");
arg_show_unit = SHOW_UNIT_SYSTEM;
if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */
return log_oom();
break;
case ARG_USER_UNIT:
if (arg_show_unit == SHOW_UNIT_SYSTEM)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Cannot combine --user-unit with --unit.");
arg_show_unit = SHOW_UNIT_USER;
if (strv_push(&arg_names, optarg) < 0) /* push optarg if not empty */
return log_oom();

View File

@ -905,8 +905,16 @@ static int get_supplementary_groups(
bool keep_groups = false;
if (user && gid_is_valid(gid) && gid != 0) {
/* First step, initialize groups from /etc/groups */
if (initgroups(user, gid) < 0)
return -errno;
if (initgroups(user, gid) < 0) {
/* If our primary gid is already the one specified in Group= (i.e. we're running in
* user mode), gracefully handle the case where we have no privilege to re-initgroups().
*
* Note that group memberships of the current user might have been modified, but
* the change will only take effect after re-login. It's better to continue on with
* existing credentials rather than erroring out. */
if (!ERRNO_IS_PRIVILEGE(errno) || gid != getgid())
return -errno;
}
keep_groups = true;
}
@ -1230,6 +1238,11 @@ static int exec_context_get_tty_for_pam(const ExecContext *context, char **ret)
return 1;
}
if (!IN_SET(context->std_input, EXEC_INPUT_TTY, EXEC_INPUT_TTY_FAIL, EXEC_INPUT_TTY_FORCE)) {
*ret = NULL;
return 0;
}
/* Next, let's try to use the TTY specified in TTYPath=. */
const char *t = exec_context_tty_path(context);
if (!t) {
@ -4469,6 +4482,12 @@ static void log_command_line(
static bool exec_needs_cap_sys_admin(const ExecContext *context, const ExecParameters *params) {
assert(context);
assert(params);
/* We only want to ever imply PrivateUsers= for user managers, as they're not expected to setuid() to
* other users, unlike the system manager which needs all users to be around. */
if (params->runtime_scope != RUNTIME_SCOPE_USER)
return false;
return context->private_users != PRIVATE_USERS_NO ||
context->private_tmp != PRIVATE_TMP_NO ||

View File

@ -1390,6 +1390,7 @@ static int mount_start(Unit *u) {
static int mount_stop(Unit *u) {
Mount *m = ASSERT_PTR(MOUNT(u));
int r;
switch (m->state) {
@ -1401,21 +1402,22 @@ static int mount_stop(Unit *u) {
case MOUNT_MOUNTING:
case MOUNT_MOUNTING_DONE:
case MOUNT_REMOUNTING:
/* If we are still waiting for /bin/mount, we go directly into kill mode. */
mount_enter_signal(m, MOUNT_UNMOUNTING_SIGTERM, MOUNT_SUCCESS);
return 0;
case MOUNT_REMOUNTING:
case MOUNT_REMOUNTING_SIGTERM:
/* If we are already waiting for a hung remount, convert this to the matching unmounting state */
mount_set_state(m, MOUNT_UNMOUNTING_SIGTERM);
return 0;
assert(pidref_is_set(&m->control_pid));
r = pidref_kill_and_sigcont(&m->control_pid, SIGKILL);
if (r < 0)
log_unit_debug_errno(u, r,
"Failed to kill remount process " PID_FMT ", ignoring: %m",
m->control_pid.pid);
_fallthrough_;
case MOUNT_REMOUNTING_SIGKILL:
/* as above */
mount_set_state(m, MOUNT_UNMOUNTING_SIGKILL);
return 0;
case MOUNT_MOUNTED:
mount_enter_unmounting(m);
return 1;
@ -2404,7 +2406,6 @@ char* mount_get_where_escaped(const Mount *m) {
}
char* mount_get_what_escaped(const Mount *m) {
_cleanup_free_ char *escaped = NULL;
const char *s = NULL;
assert(m);
@ -2413,14 +2414,10 @@ char* mount_get_what_escaped(const Mount *m) {
s = m->parameters_proc_self_mountinfo.what;
else if (m->from_fragment && m->parameters_fragment.what)
s = m->parameters_fragment.what;
if (!s)
return strdup("");
if (s) {
escaped = utf8_escape_invalid(s);
if (!escaped)
return NULL;
}
return escaped ? TAKE_PTR(escaped) : strdup("");
return utf8_escape_invalid(s);
}
char* mount_get_options_escaped(const Mount *m) {

View File

@ -366,6 +366,18 @@
send_interface="org.freedesktop.systemd1.Manager"
send_member="SetShowStatus"/>
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
send_member="SetEnvironment"/>
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
send_member="UnsetEnvironment"/>
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
send_member="UnsetAndSetEnvironment"/>
<!-- Managed via polkit or other criteria: org.freedesktop.systemd1.Job interface -->
<allow send_destination="org.freedesktop.systemd1"

View File

@ -414,7 +414,7 @@ static void service_extend_timeout(Service *s, usec_t extend_timeout_usec) {
static void service_reset_watchdog(Service *s) {
assert(s);
if (freezer_state_finish(UNIT(s)->freezer_state) != FREEZER_RUNNING) {
if (freezer_state_objective(UNIT(s)->freezer_state) != FREEZER_RUNNING) {
log_unit_debug(UNIT(s), "Service is currently %s, skipping resetting watchdog.",
freezer_state_to_string(UNIT(s)->freezer_state));
return;
@ -1425,7 +1425,7 @@ static int service_coldplug(Unit *u) {
(void) unit_setup_exec_runtime(u);
if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, SERVICE_REFRESH_EXTENSIONS, SERVICE_MOUNTING) &&
freezer_state_finish(u->freezer_state) == FREEZER_RUNNING)
freezer_state_objective(u->freezer_state) == FREEZER_RUNNING)
service_start_watchdog(s);
if (UNIT_ISSET(s->accept_socket)) {
@ -5643,18 +5643,33 @@ int service_determine_exec_selinux_label(Service *s, char **ret) {
return 0;
}
static int service_cgroup_freezer_action(Unit *u, FreezerAction action) {
static int service_freezer_action(Unit *u, FreezerAction action) {
Service *s = ASSERT_PTR(SERVICE(u));
FreezerState old_objective, new_objective;
int r;
old_objective = freezer_state_objective(u->freezer_state);
r = unit_cgroup_freezer_action(u, action);
if (r <= 0)
if (r < 0)
return r;
if (action == FREEZER_FREEZE)
service_stop_watchdog(s);
else if (action == FREEZER_THAW)
service_reset_watchdog(s);
new_objective = freezer_state_objective(u->freezer_state);
/* Note that we cannot trivially check the retval of unit_cgroup_freezer_action() here, since
* that signals whether the operation is ongoing from *kernel's PoV*. If the freeze operation
* is aborted, the frozen attribute of the cgroup would never have been flipped in kernel,
* and unit_cgroup_freezer_action() will happily return 0, yet the watchdog still needs to be reset;
* vice versa. */
if (old_objective != new_objective) {
if (new_objective == FREEZER_FROZEN)
service_stop_watchdog(s);
else if (new_objective == FREEZER_RUNNING)
service_reset_watchdog(s);
else
assert_not_reached();
}
return r;
}
@ -5796,7 +5811,7 @@ const UnitVTable service_vtable = {
.live_mount = service_live_mount,
.can_live_mount = service_can_live_mount,
.freezer_action = service_cgroup_freezer_action,
.freezer_action = service_freezer_action,
.serialize = service_serialize,
.deserialize_item = service_deserialize_item,

View File

@ -392,7 +392,8 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
continue;
if (v->base == TIMER_CALENDAR) {
usec_t b, rebased, random_offset = 0;
bool rebase_after_boot_time = false;
usec_t b, random_offset = 0;
if (t->random_offset_usec != 0)
random_offset = timer_get_fixed_delay_hash(t) % t->random_offset_usec;
@ -417,8 +418,10 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
b = t->last_trigger.realtime;
else if (dual_timestamp_is_set(&UNIT(t)->inactive_exit_timestamp))
b = UNIT(t)->inactive_exit_timestamp.realtime - random_offset;
else
else {
b = ts.realtime - random_offset;
rebase_after_boot_time = true;
}
r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
if (r < 0)
@ -426,14 +429,16 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
v->next_elapse += random_offset;
/* To make the delay due to RandomizedDelaySec= work even at boot, if the scheduled
* time has already passed, set the time when systemd first started as the scheduled
* time. Note that we base this on the monotonic timestamp of the boot, not the
* realtime one, since the wallclock might have been off during boot. */
rebased = map_clock_usec(UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic,
CLOCK_MONOTONIC, CLOCK_REALTIME);
if (v->next_elapse < rebased)
v->next_elapse = rebased;
if (rebase_after_boot_time) {
/* To make the delay due to RandomizedDelaySec= work even at boot, if the scheduled
* time has already passed, set the time when systemd first started as the scheduled
* time. Note that we base this on the monotonic timestamp of the boot, not the
* realtime one, since the wallclock might have been off during boot. */
usec_t rebased = map_clock_usec(UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic,
CLOCK_MONOTONIC, CLOCK_REALTIME);
if (v->next_elapse < rebased)
v->next_elapse = rebased;
}
if (!found_realtime)
t->next_elapse_realtime = v->next_elapse;

View File

@ -6436,9 +6436,7 @@ void unit_next_freezer_state(Unit *u, FreezerAction action, FreezerState *ret_ne
assert_not_reached();
}
objective = freezer_state_finish(next);
if (objective == FREEZER_FROZEN_BY_PARENT)
objective = FREEZER_FROZEN;
objective = freezer_state_objective(next);
assert(IN_SET(objective, FREEZER_RUNNING, FREEZER_FROZEN));
*ret_next = next;

View File

@ -1294,7 +1294,7 @@ static int send_iovec(const struct iovec_wrapper *iovw, int input_fd, PidRef *pi
if (sendmsg(fd, &mh, MSG_NOSIGNAL) >= 0)
break;
if (errno == EMSGSIZE && mh.msg_iov[0].iov_len > 0) {
if (IN_SET(errno, EMSGSIZE, ENOBUFS) && mh.msg_iov[0].iov_len > 0) {
/* This field didn't fit? That's a pity. Given that this is
* just metadata, let's truncate the field at half, and try
* again. We append three dots, in order to show that this is

View File

@ -543,7 +543,7 @@ static int resolve_filename(const char *root, char **p) {
static int print_list(FILE* file, sd_journal *j, Table *t) {
_cleanup_free_ char
*mid = NULL, *pid = NULL, *uid = NULL, *gid = NULL,
*sgnl = NULL, *exe = NULL, *comm = NULL, *cmdline = NULL,
*sgnl = NULL, *exe = NULL, *comm = NULL,
*filename = NULL, *truncated = NULL, *coredump = NULL;
const void *d;
size_t l;
@ -568,14 +568,16 @@ static int print_list(FILE* file, sd_journal *j, Table *t) {
RETRIEVE(d, l, "COREDUMP_SIGNAL", sgnl);
RETRIEVE(d, l, "COREDUMP_EXE", exe);
RETRIEVE(d, l, "COREDUMP_COMM", comm);
RETRIEVE(d, l, "COREDUMP_CMDLINE", cmdline);
RETRIEVE(d, l, "COREDUMP_FILENAME", filename);
RETRIEVE(d, l, "COREDUMP_TRUNCATED", truncated);
RETRIEVE(d, l, "COREDUMP", coredump);
}
if (!pid && !uid && !gid && !sgnl && !exe && !comm && !cmdline && !filename)
return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Empty coredump log entry");
if (!pid || !uid || !gid || !sgnl || !comm) {
log_warning("Found a coredump entry without mandatory fields (PID=%s, UID=%s, GID=%s, SIGNAL=%s, COMM=%s), ignoring.",
strna(pid), strna(uid), strna(gid), strna(sgnl), strna(comm));
return 0;
}
(void) parse_uid(uid, &uid_as_int);
(void) parse_gid(gid, &gid_as_int);
@ -614,7 +616,7 @@ static int print_list(FILE* file, sd_journal *j, Table *t) {
TABLE_SIGNAL, normal_coredump ? signal_as_int : 0,
TABLE_STRING, present,
TABLE_SET_COLOR, color,
TABLE_STRING, exe ?: comm ?: cmdline,
TABLE_STRING, exe ?: comm,
TABLE_SIZE, size);
if (r < 0)
return table_log_add_error(r);

View File

@ -7,6 +7,7 @@
#include "fileio.h"
#include "log.h"
#include "log-assert-critical.h"
/* The entry point into the fuzzer */
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);

View File

@ -3778,7 +3778,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_SETENV: {
_cleanup_free_ char **l = NULL;
_cleanup_strv_free_ char **l = NULL;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *ne = NULL;
sd_json_variant *e;

View File

@ -287,8 +287,6 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
return sd_varlink_error(link, "io.systemd.UserDatabase.BadService", NULL);
if (p.user_name) {
const char *last = NULL;
r = manager_get_home_by_name(m, p.user_name, &h);
if (r < 0)
return r;
@ -296,40 +294,37 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
if (p.group_name) {
if (!strv_contains(h->record->member_of, p.group_name))
if (!strv_contains(h->record->member_of, p.group_name) &&
!user_record_matches_user_name(h->record, p.group_name))
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
return sd_varlink_replybo(
link,
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(p.group_name)));
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
SD_JSON_BUILD_PAIR_STRING("groupName", p.group_name));
}
STRV_FOREACH(i, h->record->member_of) {
if (last) {
r = sd_varlink_notifybo(
link,
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
if (r < 0)
return r;
}
last = *i;
r = sd_varlink_notifybo(
link,
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
SD_JSON_BUILD_PAIR_STRING("groupName", *i));
if (r < 0)
return r;
}
if (last)
return sd_varlink_replybo(
link,
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
return sd_varlink_replybo(
link,
SD_JSON_BUILD_PAIR_STRING("userName", h->user_name),
SD_JSON_BUILD_PAIR_STRING("groupName", h->user_name));
} else if (p.group_name) {
const char *last = NULL;
HASHMAP_FOREACH(h, m->homes_by_uid) {
if (!strv_contains(h->record->member_of, p.group_name))
if (!strv_contains(h->record->member_of, p.group_name) &&
!user_record_matches_user_name(h->record, p.group_name))
continue;
if (last) {
@ -350,34 +345,37 @@ int vl_method_get_memberships(sd_varlink *link, sd_json_variant *parameters, sd_
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(p.group_name)));
} else {
const char *last_user_name = NULL, *last_group_name = NULL;
const char *last = NULL;
HASHMAP_FOREACH(h, m->homes_by_uid)
HASHMAP_FOREACH(h, m->homes_by_uid) {
STRV_FOREACH(j, h->record->member_of) {
if (last_user_name) {
assert(last_group_name);
if (last) {
r = sd_varlink_notifybo(
link,
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last_user_name)),
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last_group_name)));
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
if (r < 0)
return r;
last = NULL;
}
last_user_name = h->user_name;
last_group_name = *j;
r = sd_varlink_notifybo(
link,
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(h->user_name)),
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(*j)));
if (r < 0)
return r;
}
if (last_user_name) {
assert(last_group_name);
last = h->user_name;
}
if (last)
return sd_varlink_replybo(
link,
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last_user_name)),
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last_group_name)));
}
SD_JSON_BUILD_PAIR("userName", SD_JSON_BUILD_STRING(last)),
SD_JSON_BUILD_PAIR("groupName", SD_JSON_BUILD_STRING(last)));
}
return sd_varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);

View File

@ -1704,32 +1704,52 @@ static int varlink_idl_validate_field_element_type(const sd_varlink_field *field
case SD_VARLINK_BOOL:
if (!sd_json_variant_is_boolean(v))
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be a bool, but it is not, refusing.", strna(field->name));
return varlink_idl_log(
SYNTHETIC_ERRNO(EMEDIUMTYPE),
"Field '%s' should be a bool, but it is of type '%s', refusing.",
strna(field->name),
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
break;
case SD_VARLINK_INT:
/* Allow strings here too, since integers with > 53 bits are often passed in as strings */
if (!sd_json_variant_is_integer(v) && !sd_json_variant_is_unsigned(v) && !sd_json_variant_is_string(v))
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be an int, but it is not, refusing.", strna(field->name));
return varlink_idl_log(
SYNTHETIC_ERRNO(EMEDIUMTYPE),
"Field '%s' should be an int, but it is of type '%s', refusing.",
strna(field->name),
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
break;
case SD_VARLINK_FLOAT:
if (!sd_json_variant_is_number(v))
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be a float, but it is not, refusing.", strna(field->name));
return varlink_idl_log(
SYNTHETIC_ERRNO(EMEDIUMTYPE),
"Field '%s' should be a float, but it is of type '%s', refusing.",
strna(field->name),
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
break;
case SD_VARLINK_STRING:
if (!sd_json_variant_is_string(v))
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be a string, but it is not, refusing.", strna(field->name));
return varlink_idl_log(
SYNTHETIC_ERRNO(EMEDIUMTYPE),
"Field '%s' should be a string, but it is of type '%s', refusing.",
strna(field->name),
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
break;
case SD_VARLINK_OBJECT:
if (!sd_json_variant_is_object(v))
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be an object, but it is not, refusing.", strna(field->name));
return varlink_idl_log(
SYNTHETIC_ERRNO(EMEDIUMTYPE),
"Field '%s' should be an object, but it is of type '%s', refusing.",
strna(field->name),
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
break;
@ -1758,7 +1778,10 @@ static int varlink_idl_validate_field(const sd_varlink_field *field, sd_json_var
sd_json_variant *i;
if (!sd_json_variant_is_array(v))
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be an array, but it is not, refusing.", strna(field->name));
return varlink_idl_log(
SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be an array, but it is of type '%s', refusing.",
strna(field->name),
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
JSON_VARIANT_ARRAY_FOREACH(i, v) {
r = varlink_idl_validate_field_element_type(field, i);
@ -1771,7 +1794,11 @@ static int varlink_idl_validate_field(const sd_varlink_field *field, sd_json_var
sd_json_variant *e;
if (!sd_json_variant_is_object(v))
return varlink_idl_log(SYNTHETIC_ERRNO(EMEDIUMTYPE), "Field '%s' should be an object, but it is not, refusing.", strna(field->name));
return varlink_idl_log(
SYNTHETIC_ERRNO(EMEDIUMTYPE),
"Field '%s' should be an object, but it is of type '%s', refusing.",
strna(field->name),
strna(sd_json_variant_type_to_string(sd_json_variant_type(v))));
JSON_VARIANT_OBJECT_FOREACH(k, e, v) {
r = varlink_idl_validate_field_element_type(field, e);

View File

@ -464,6 +464,8 @@ static int help(void) {
" --overlay-ro=PATH[:PATH...]:PATH\n"
" Similar, but creates a read-only overlay mount\n"
" --bind-user=NAME Bind user from host to container\n"
" --bind-user-shell=BOOL|PATH\n"
" Configure the shell to use for --bind-user= users\n"
"\n%3$sInput/Output:%4$s\n"
" --console=MODE Select how stdin/stdout/stderr and /dev/console are\n"
" set up for the container.\n"

View File

@ -8,6 +8,7 @@
#include "errno-util.h"
#include "hostname-setup.h"
#include "hostname-util.h"
#include "in-addr-util.h"
#include "local-addresses.h"
#include "nss-util.h"
#include "resolve-util.h"
@ -116,7 +117,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
r_tuple->next = r_tuple_prev;
r_tuple->name = r_name;
r_tuple->family = AF_INET6;
memcpy(r_tuple->addr, LOCALADDRESS_IPV6, 16);
memcpy(r_tuple->addr, LOCALADDRESS_IPV6, FAMILY_ADDRESS_SIZE(AF_INET6));
r_tuple->scopeid = 0;
idx += ALIGN(sizeof(struct gaih_addrtuple));
@ -144,7 +145,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r(
r_tuple->name = r_name;
r_tuple->family = a->family;
r_tuple->scopeid = a->family == AF_INET6 && in6_addr_is_link_local(&a->address.in6) ? a->ifindex : 0;
memcpy(r_tuple->addr, &a->address, 16);
memcpy(r_tuple->addr, &a->address, FAMILY_ADDRESS_SIZE(a->family));
idx += ALIGN(sizeof(struct gaih_addrtuple));
r_tuple_prev = r_tuple;
@ -263,7 +264,7 @@ static enum nss_status fill_in_hostent(
*(uint32_t*) r_addr = local_address_ipv4;
idx += ALIGN(alen);
} else if (socket_ipv6_is_enabled()) {
memcpy(r_addr, LOCALADDRESS_IPV6, 16);
memcpy(r_addr, LOCALADDRESS_IPV6, FAMILY_ADDRESS_SIZE(AF_INET6));
idx += ALIGN(alen);
}
@ -463,7 +464,7 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r(
if (!socket_ipv6_is_enabled())
goto not_found;
if (memcmp(addr, LOCALADDRESS_IPV6, 16) == 0) {
if (memcmp(addr, LOCALADDRESS_IPV6, FAMILY_ADDRESS_SIZE(AF_INET6)) == 0) {
canonical = "localhost";
additional_from_hostname = true;
goto found;

View File

@ -418,7 +418,7 @@ enum nss_status _nss_resolve_gethostbyname3_r(
if (r < 0)
goto fail;
if (!IN_SET(q.family, AF_INET, AF_INET6))
if (q.family != af)
continue;
if (q.address_size != FAMILY_ADDRESS_SIZE(q.family)) {

View File

@ -726,7 +726,7 @@ enum nss_status _nss_systemd_getgrent_r(
int *errnop) {
_cleanup_(group_record_unrefp) GroupRecord *gr = NULL;
_cleanup_free_ char **members = NULL;
_cleanup_strv_free_ char **members = NULL;
int r;
PROTECT_ERRNO;

View File

@ -21,7 +21,6 @@
# Cloudflare: 1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 2606:4700:4700::1001#cloudflare-dns.com
# Google: 8.8.8.8#dns.google 8.8.4.4#dns.google 2001:4860:4860::8888#dns.google 2001:4860:4860::8844#dns.google
# Quad9: 9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net
# DNS0: 193.110.81.0#dns0.eu 185.253.5.0#dns0.eu 2a0f:fc80::#dns0.eu 2a0f:fc81::#dns0.eu
#
# Using DNS= configures global DNS servers and does not suppress link-specific
# configuration. Parallel requests will be sent to per-link DNS servers

View File

@ -8,17 +8,17 @@
#
# Minimum rpm version supported: 4.14.0
%transfiletriggerin -P 900900 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
%transfiletriggerin -P 900900 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
-- This script will run after any package is initially installed or
-- upgraded. We care about the case where a package is initially
-- installed, because other cases are covered by the *un scriptlets,
-- so sometimes we will reload needlessly.
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-reload-restart"))
%transfiletriggerin -P 900899 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
%transfiletriggerin -P 900899 -p <lua> -- {{USER_DATA_UNIT_DIR}}/ /etc/systemd/user/
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload-restart"))
%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
-- On removal, we need to run daemon-reload after any units have been
-- removed.
-- On upgrade, we need to run daemon-reload after any new unit files
@ -26,53 +26,53 @@ assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload-restart"))
-- executed.
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-reload"))
%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
-- Execute daemon-reload in user managers.
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload"))
%transfiletriggerpostun -P 10000 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
%transfiletriggerpostun -P 10000 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
-- We restart remaining system services that should be restarted here.
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-restart"))
%transfiletriggerpostun -P 9999 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
%transfiletriggerpostun -P 9999 -p <lua> -- {{USER_DATA_UNIT_DIR}}/ /etc/systemd/user/
-- We restart remaining user services that should be restarted here.
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-restart"))
%transfiletriggerin -P 1000700 -p <lua> -- {{SYSUSERS_DIR}}
%transfiletriggerin -P 1000700 -p <lua> -- {{SYSUSERS_DIR}}/
-- This script will process files installed in {{SYSUSERS_DIR}} to create
-- specified users automatically. The priority is set such that it
-- will run before the tmpfiles file trigger.
assert(rpm.execute("systemd-sysusers"))
%transfiletriggerin -P 1000700 udev -p <lua> -- {{UDEV_HWDB_DIR}}
%transfiletriggerin -P 1000700 udev -p <lua> -- {{UDEV_HWDB_DIR}}/
-- This script will automatically invoke hwdb update if files have been
-- installed or updated in {{UDEV_HWDB_DIR}}.
assert(rpm.execute("systemd-hwdb", "update"))
%transfiletriggerin -P 1000700 -p <lua> -- {{SYSTEMD_CATALOG_DIR}}
%transfiletriggerin -P 1000700 -p <lua> -- {{SYSTEMD_CATALOG_DIR}}/
-- This script will automatically invoke journal catalog update if files
-- have been installed or updated in {{SYSTEMD_CATALOG_DIR}}.
assert(rpm.execute("journalctl", "--update-catalog"))
%transfiletriggerin -P 1000700 -p <lua> -- {{BINFMT_DIR}}
%transfiletriggerin -P 1000700 -p <lua> -- {{BINFMT_DIR}}/
-- This script will automatically apply binfmt rules if files have been
-- installed or updated in {{BINFMT_DIR}}.
if posix.access("/run/systemd/system") then
assert(rpm.execute("{{LIBEXECDIR}}/systemd-binfmt"))
end
%transfiletriggerin -P 1000600 -p <lua> -- {{TMPFILES_DIR}}
%transfiletriggerin -P 1000600 -p <lua> -- {{TMPFILES_DIR}}/
-- This script will process files installed in {{TMPFILES_DIR}} to create
-- tmpfiles automatically. The priority is set such that it will run
-- after the sysusers file trigger, but before any other triggers.
assert(rpm.execute("systemd-tmpfiles", "--create"))
%transfiletriggerin -P 1000600 udev -p <lua> -- {{UDEV_RULES_DIR}}
%transfiletriggerin -P 1000600 udev -p <lua> -- {{UDEV_RULES_DIR}}/
-- This script will automatically update udev with new rules if files
-- have been installed or updated in {{UDEV_RULES_DIR}}.
assert(rpm.execute("{{SYSTEMD_UPDATE_HELPER_PATH}}", "mark-reload-system-units", "systemd-udevd.service"))
%transfiletriggerin -P 1000500 -p <lua> -- {{SYSCTL_DIR}}
%transfiletriggerin -P 1000500 -p <lua> -- {{SYSCTL_DIR}}/
-- This script will automatically apply sysctl rules if files have been
-- installed or updated in {{SYSCTL_DIR}}.
if posix.access("/run/systemd/system") then

View File

@ -9,17 +9,17 @@
#
# Minimum rpm version supported: 4.14.0
%transfiletriggerin -P 900900 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
%transfiletriggerin -P 900900 -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
# This script will run after any package is initially installed or
# upgraded. We care about the case where a package is initially
# installed, because other cases are covered by the *un scriptlets,
# so sometimes we will reload needlessly.
{{SYSTEMD_UPDATE_HELPER_PATH}} system-reload-restart || :
%transfiletriggerin -P 900899 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
%transfiletriggerin -P 900899 -- {{USER_DATA_UNIT_DIR}}/ /etc/systemd/user/
{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload-restart || :
%transfiletriggerpostun -P 1000100 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
%transfiletriggerpostun -P 1000100 -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
# On removal, we need to run daemon-reload after any units have been
# removed.
# On upgrade, we need to run daemon-reload after any new unit files
@ -27,35 +27,35 @@
# executed.
{{SYSTEMD_UPDATE_HELPER_PATH}} system-reload || :
%transfiletriggerpostun -P 1000099 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
%transfiletriggerpostun -P 1000099 -- {{USER_DATA_UNIT_DIR}}/ /etc/systemd/user/
# Execute daemon-reload in user managers.
{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload || :
%transfiletriggerpostun -P 10000 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
%transfiletriggerpostun -P 10000 -- {{SYSTEM_DATA_UNIT_DIR}}/ /etc/systemd/system/
# We restart remaining system services that should be restarted here.
{{SYSTEMD_UPDATE_HELPER_PATH}} system-restart || :
%transfiletriggerpostun -P 9999 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
%transfiletriggerpostun -P 9999 -- {{USER_DATA_UNIT_DIR}}/ /etc/systemd/user/
# We restart remaining user services that should be restarted here.
{{SYSTEMD_UPDATE_HELPER_PATH}} user-restart || :
%transfiletriggerin -P 1000700 -- {{SYSUSERS_DIR}}
%transfiletriggerin -P 1000700 -- {{SYSUSERS_DIR}}/
# This script will process files installed in {{SYSUSERS_DIR}} to create
# specified users automatically. The priority is set such that it
# will run before the tmpfiles file trigger.
systemd-sysusers || :
%transfiletriggerin -P 1000700 udev -- {{UDEV_HWDB_DIR}}
%transfiletriggerin -P 1000700 udev -- {{UDEV_HWDB_DIR}}/
# This script will automatically invoke hwdb update if files have been
# installed or updated in {{UDEV_HWDB_DIR}}.
systemd-hwdb update || :
%transfiletriggerin -P 1000700 -- {{SYSTEMD_CATALOG_DIR}}
%transfiletriggerin -P 1000700 -- {{SYSTEMD_CATALOG_DIR}}/
# This script will automatically invoke journal catalog update if files
# have been installed or updated in {{SYSTEMD_CATALOG_DIR}}.
journalctl --update-catalog || :
%transfiletriggerin -P 1000700 -- {{BINFMT_DIR}}
%transfiletriggerin -P 1000700 -- {{BINFMT_DIR}}/
# This script will automatically apply binfmt rules if files have been
# installed or updated in {{BINFMT_DIR}}.
if test -d "/run/systemd/system"; then
@ -64,7 +64,7 @@ if test -d "/run/systemd/system"; then
{{LIBEXECDIR}}/systemd-binfmt || :
fi
%transfiletriggerin -P 1000600 -- {{TMPFILES_DIR}}
%transfiletriggerin -P 1000600 -- {{TMPFILES_DIR}}/
# This script will process files installed in {{TMPFILES_DIR}} to create
# tmpfiles automatically. The priority is set such that it will run
# after the sysusers file trigger, but before any other triggers.
@ -72,12 +72,12 @@ if test -d "/run/systemd/system"; then
systemd-tmpfiles --create || :
fi
%transfiletriggerin -P 1000600 udev -- {{UDEV_RULES_DIR}}
%transfiletriggerin -P 1000600 udev -- {{UDEV_RULES_DIR}}/
# This script will automatically update udev with new rules if files
# have been installed or updated in {{UDEV_RULES_DIR}}.
{{SYSTEMD_UPDATE_HELPER_PATH}} mark-reload-system-units systemd-udevd.service || :
%transfiletriggerin -P 1000500 -- {{SYSCTL_DIR}}
%transfiletriggerin -P 1000500 -- {{SYSCTL_DIR}}/
# This script will automatically apply sysctl rules if files have been
# installed or updated in {{SYSCTL_DIR}}.
if test -d "/run/systemd/system"; then

View File

@ -1133,6 +1133,8 @@ static int ask_password_credential(const AskPasswordRequest *req, AskPasswordFla
r = read_credential(req->credential, (void**) &buffer, &size);
if (IN_SET(r, -ENXIO, -ENOENT)) /* No credentials passed or this credential not defined? */
return -ENOKEY;
if (r < 0)
return r;
l = strv_parse_nulstr(buffer, size);
if (!l)

View File

@ -49,6 +49,8 @@ DLSYM_PROTOTYPE(ring_buffer__free) = NULL;
DLSYM_PROTOTYPE(ring_buffer__new) = NULL;
DLSYM_PROTOTYPE(ring_buffer__poll) = NULL;
static void* bpf_dl = NULL;
/* new symbols available from libbpf 0.7.0 */
int (*sym_bpf_map_create)(enum bpf_map_type, const char *, __u32, __u32, __u32, const struct bpf_map_create_opts *);
struct bpf_map* (*sym_bpf_object__next_map)(const struct bpf_object *obj, const struct bpf_map *map);
@ -71,8 +73,8 @@ static int bpf_print_func(enum libbpf_print_level level, const char *fmt, va_lis
}
int dlopen_bpf_full(int log_level) {
_cleanup_(dlclosep) void *dl = NULL;
static int cached = 0;
void *dl;
int r;
if (cached != 0)
@ -177,6 +179,8 @@ int dlopen_bpf_full(int log_level) {
REENABLE_WARNING;
bpf_dl = TAKE_PTR(dl);
return cached = true;
}

View File

@ -567,6 +567,7 @@ static int image_make(
static int pick_image_search_path(
RuntimeScope scope,
ImageClass class,
const char *root,
char ***ret) {
int r;
@ -583,11 +584,11 @@ static int pick_image_search_path(
if (scope < 0) {
_cleanup_strv_free_ char **a = NULL, **b = NULL;
r = pick_image_search_path(RUNTIME_SCOPE_USER, class, &a);
r = pick_image_search_path(RUNTIME_SCOPE_USER, class, root, &a);
if (r < 0)
return r;
r = pick_image_search_path(RUNTIME_SCOPE_SYSTEM, class, &b);
r = pick_image_search_path(RUNTIME_SCOPE_SYSTEM, class, root, &b);
if (r < 0)
return r;
@ -603,8 +604,15 @@ static int pick_image_search_path(
case RUNTIME_SCOPE_SYSTEM: {
const char *ns;
bool is_initrd;
r = chase_and_access("/etc/initrd-release", root, CHASE_PREFIX_ROOT, F_OK, /* ret_path= */ NULL);
if (r < 0 && r != -ENOENT)
return r;
is_initrd = r >= 0;
/* Use the initrd search path if there is one, otherwise use the common one */
ns = in_initrd() && image_search_path_initrd[class] ?
ns = is_initrd && image_search_path_initrd[class] ?
image_search_path_initrd[class] :
image_search_path[class];
if (!ns)
@ -711,7 +719,7 @@ int image_find(RuntimeScope scope,
return -ENOMEM;
_cleanup_strv_free_ char **search = NULL;
r = pick_image_search_path(scope, class, &search);
r = pick_image_search_path(scope, class, root, &search);
if (r < 0)
return r;
@ -902,7 +910,7 @@ int image_discover(
assert(images);
_cleanup_strv_free_ char **search = NULL;
r = pick_image_search_path(scope, class, &search);
r = pick_image_search_path(scope, class, root, &search);
if (r < 0)
return r;
@ -1797,7 +1805,7 @@ bool image_in_search_path(
assert(image);
_cleanup_strv_free_ char **search = NULL;
r = pick_image_search_path(scope, class, &search);
r = pick_image_search_path(scope, class, root, &search);
if (r < 0)
return r;

View File

@ -4405,8 +4405,6 @@ int verity_dissect_and_mount(
_cleanup_strv_free_ char **extension_release = NULL;
ImageClass class = IMAGE_SYSEXT;
assert(!isempty(extension_release_data->os_release_id));
r = load_extension_release_pairs(dest, required_class >= 0 ? required_class : IMAGE_SYSEXT, dissected_image->image_name, relax_extension_release_check, &extension_release);
if (r == -ENOENT) {
if (required_class >= 0)

View File

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "env-util.h"
#include "log.h"
#include "log-assert-critical.h"
static bool assert_return_is_critical = BUILD_MODE_DEVELOPER;
void log_set_assert_return_is_critical(bool b) {
assert_return_is_critical = b;
}
void log_set_assert_return_is_critical_from_env(void) {
static int cached = INT_MIN;
int r;
if (cached == INT_MIN) {
r = secure_getenv_bool("SYSTEMD_ASSERT_RETURN_IS_CRITICAL");
if (r < 0 && r != -ENXIO)
log_debug_errno(r, "Failed to parse $SYSTEMD_ASSERT_RETURN_IS_CRITICAL, ignoring: %m");
cached = r;
}
if (cached >= 0)
log_set_assert_return_is_critical(cached);
}
bool log_get_assert_return_is_critical(void) {
return assert_return_is_critical;
}

View File

@ -0,0 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "forward.h"
void log_set_assert_return_is_critical(bool b);
void log_set_assert_return_is_critical_from_env(void);

View File

@ -34,14 +34,14 @@ static int check_etc_passwd_collisions(
if (r == -ENOENT)
return 0; /* no user database? then no user, hence no collision */
if (r < 0)
return log_error_errno(r, "Failed to open /etc/passwd of container: %m");
return log_error_errno(r, "Failed to open /etc/passwd of machine: %m");
for (;;) {
struct passwd *pw;
r = fgetpwent_sane(f, &pw);
if (r < 0)
return log_error_errno(r, "Failed to iterate through /etc/passwd of container: %m");
return log_error_errno(r, "Failed to iterate through /etc/passwd of machine: %m");
if (r == 0) /* EOF */
return 0; /* no collision */
@ -69,14 +69,14 @@ static int check_etc_group_collisions(
if (r == -ENOENT)
return 0; /* no group database? then no group, hence no collision */
if (r < 0)
return log_error_errno(r, "Failed to open /etc/group of container: %m");
return log_error_errno(r, "Failed to open /etc/group of machine: %m");
for (;;) {
struct group *gr;
r = fgetgrent_sane(f, &gr);
if (r < 0)
return log_error_errno(r, "Failed to iterate through /etc/group of container: %m");
return log_error_errno(r, "Failed to iterate through /etc/group of machine: %m");
if (r == 0)
return 0; /* no collision */
@ -115,14 +115,14 @@ static int convert_user(
return r;
if (r > 0)
return log_error_errno(SYNTHETIC_ERRNO(EBUSY),
"Sorry, the user '%s' already exists in the container.", u->user_name);
"Sorry, the user '%s' already exists in the machine.", u->user_name);
r = check_etc_group_collisions(directory, g->group_name, GID_INVALID);
if (r < 0)
return r;
if (r > 0)
return log_error_errno(SYNTHETIC_ERRNO(EBUSY),
"Sorry, the group '%s' already exists in the container.", g->group_name);
"Sorry, the group '%s' already exists in the machine.", g->group_name);
h = path_join("/run/host/home/", u->user_name);
if (!h)
@ -149,7 +149,7 @@ static int convert_user(
SD_JSON_BUILD_PAIR_CONDITION(!strv_isempty(u->hashed_password), "hashedPassword", SD_JSON_BUILD_VARIANT(hp)),
SD_JSON_BUILD_PAIR_CONDITION(!!ssh, "sshAuthorizedKeys", SD_JSON_BUILD_VARIANT(ssh))))));
if (r < 0)
return log_error_errno(r, "Failed to build container user record: %m");
return log_error_errno(r, "Failed to build machine user record: %m");
r = group_record_build(
&converted_group,
@ -159,7 +159,7 @@ static int convert_user(
SD_JSON_BUILD_PAIR_CONDITION(g->disposition >= 0, "disposition", SD_JSON_BUILD_STRING(user_disposition_to_string(g->disposition))),
SD_JSON_BUILD_PAIR("service", JSON_BUILD_CONST_STRING("io.systemd.NSpawn"))));
if (r < 0)
return log_error_errno(r, "Failed to build container group record: %m");
return log_error_errno(r, "Failed to build machine group record: %m");
*ret_converted_user = TAKE_PTR(converted_user);
*ret_converted_group = TAKE_PTR(converted_group);
@ -176,7 +176,7 @@ static int find_free_uid(const char *directory, uid_t *current_uid) {
if (*current_uid > MAP_UID_MAX)
return log_error_errno(
SYNTHETIC_ERRNO(EBUSY),
"No suitable available UID in range " UID_FMT "" UID_FMT " in container detected, can't map user.",
"No suitable available UID in range " UID_FMT "" UID_FMT " in machine detected, can't map user.",
MAP_UID_MIN, MAP_UID_MAX);
r = check_etc_passwd_collisions(directory, NULL, *current_uid);
@ -220,7 +220,7 @@ int machine_bind_user_prepare(
assert(ret);
/* This resolves the users specified in 'bind_user', generates a minimalized JSON user + group record
* for it to stick in the container, allocates a UID/GID for it, and updates the custom mount table,
* for it to stick in the machine, allocates a UID/GID for it, and updates the custom mount table,
* to include an appropriate bind mount mapping.
*
* This extends the passed custom_mounts/n_custom_mounts with the home directories, and allocates a
@ -265,13 +265,13 @@ int machine_bind_user_prepare(
if (r < 0)
return log_error_errno(r, "Failed to resolve group of user '%s': %m", u->user_name);
/* We want to synthesize exactly one user + group from the host into the container. This only
/* We want to synthesize exactly one user + group from the host into the machine. This only
* makes sense if the user on the host has its own private group. We can't reasonably check
* this, so we just check of the name of user and group match.
*
* One of these days we might want to support users in a shared/common group too, but it's
* not clear to me how this would have to be mapped, precisely given that the common group
* probably already exists in the container. */
* probably already exists in the machine. */
if (!streq(u->user_name, g->group_name))
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"Sorry, mapping users without private groups is currently not supported.");

View File

@ -115,6 +115,7 @@ shared_sources = files(
'libmount-util.c',
'local-addresses.c',
'locale-setup.c',
'log-assert-critical.c',
'logs-show.c',
'loop-util.c',
'loopback-setup.c',

View File

@ -400,8 +400,8 @@ int nsresource_add_netif_tap(
return log_debug_errno(sd_varlink_error_to_errno(error_id, reply), "Failed to add network to user namespace: %s", error_id);
static const sd_json_dispatch_field dispatch_table[] = {
{ "hostInterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(InterfaceParams, host_interface_name), SD_JSON_MANDATORY },
{ "interfaceFileDescriptor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, offsetof(InterfaceParams, namespace_interface_name), SD_JSON_MANDATORY },
{ "hostInterfaceName", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, offsetof(InterfaceParams, host_interface_name), SD_JSON_MANDATORY },
{ "interfaceFileDescriptor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, offsetof(InterfaceParams, interface_fd_index), SD_JSON_MANDATORY },
};
_cleanup_(interface_params_done) InterfaceParams p = {};

View File

@ -6,6 +6,7 @@
#include "assert-util.h"
#include "log.h"
#include "log-assert-critical.h"
#include "nss-util.h"
sd_json_dispatch_flags_t nss_json_dispatch_flags = SD_JSON_ALLOW_EXTENSIONS;

View File

@ -449,12 +449,18 @@ int rm_rf_at(int dir_fd, const char *path, RemoveFlags flags) {
if (FLAGS_SET(flags, REMOVE_MISSING_OK) && r == -ENOENT)
return 0;
if (!IN_SET(r, -ENOTTY, -EINVAL, -ENOTDIR))
if (!IN_SET(r, -ENOTTY, -EINVAL, -ENOTDIR, -EPERM, -EACCES))
return r;
/* Not btrfs or not a subvolume */
/* Not btrfs or not a subvolume, or permissions are not available (but might if we go via unlinkat()) */
}
/* In the next step we'll try to open the directory in order to enumerate its contents. This might
* not work due to perms, but we might still be able to delete it, hence let's try that first. */
if (FLAGS_SET(flags, REMOVE_ROOT | REMOVE_PHYSICAL))
if (unlinkat(dir_fd, path, AT_REMOVEDIR) >= 0)
return 0;
fd = openat_harder(dir_fd, path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME, flags, &old_mode);
if (fd >= 0) {
/* We have a dir */

View File

@ -7,6 +7,7 @@
#include "errno-util.h"
#include "forward.h"
#include "log.h"
#include "log-assert-critical.h"
#include "static-destruct.h"
#include "signal-util.h"
#include "stdio-util.h"

View File

@ -1662,9 +1662,11 @@ static const ImagePolicy *pick_image_policy(const Image *img) {
/* If located in /.extra/ in the initrd, then it was placed there by systemd-stub, and was
* picked up from an untrusted ESP. Thus, require a stricter policy by default for them. (For the
* other directories we assume the appropriate level of trust was already established already. */
* other directories we assume the appropriate level of trust was already established.)
* With --root= we default to the regular policy, though. (To change that, the check would need
* to prepend (or cut away) arg_root.) */
if (in_initrd()) {
if (in_initrd() && !arg_root) {
if (path_startswith(img->path, "/.extra/sysext/"))
return &image_policy_sysext_strict;
if (path_startswith(img->path, "/.extra/global_sysext/"))
@ -1860,13 +1862,19 @@ static int merge_subprocess(
if (force)
log_debug("Force mode enabled, skipping version validation.");
else {
bool is_initrd;
r = chase_and_access("/etc/initrd-release", arg_root, CHASE_PREFIX_ROOT, F_OK, /* ret_path= */ NULL);
if (r < 0 && r != -ENOENT)
return log_error_errno(r, "Failed to check for /etc/initrd-release: %m");
is_initrd = r >= 0;
r = extension_release_validate(
img->name,
host_os_release_id,
host_os_release_id_like,
host_os_release_version_id,
host_os_release_api_level,
in_initrd() ? "initrd" : "system",
is_initrd ? "initrd" : "system",
image_extension_release(img, image_class),
image_class);
if (r < 0)

View File

@ -44,7 +44,7 @@ int verb_add_dependency(int argc, char *argv[], void *userdata) {
else
assert_not_reached();
if (install_client_side()) {
if (install_client_side() != INSTALL_CLIENT_SIDE_NO) {
InstallChange *changes = NULL;
size_t n_changes = 0;

View File

@ -96,8 +96,28 @@ static int parse_shutdown_time_spec(const char *t, usec_t *ret) {
if (r < 0)
return r;
while (s <= n)
s += USEC_PER_DAY;
if (s <= n) {
/* The specified time is today, but in the past. We need to schedule it for tomorrow
* at the same time. Adding USEC_PER_DAY would be wrong across DST changes, so just
* let mktime() normalise it. */
int requested_hour = tm.tm_hour;
int requested_min = tm.tm_min;
tm.tm_mday++;
tm.tm_isdst = -1;
r = mktime_or_timegm_usec(&tm, /* utc= */ false, &s);
if (r < 0)
return r;
if (tm.tm_hour != requested_hour || tm.tm_min != requested_min) {
log_warning("Requested shutdown time %02d:%02d does not exist. "
"Rescheduling to %02d:%02d.",
requested_hour,
requested_min,
tm.tm_hour,
tm.tm_min);
}
}
*ret = s;
}

View File

@ -370,7 +370,8 @@ int verb_edit(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
if (!arg_no_reload && !install_client_side()) {
if (!arg_no_reload &&
install_client_side() == INSTALL_CLIENT_SIDE_NO) {
r = daemon_reload(ACTION_RELOAD, /* graceful= */ false);
if (r < 0)
return r;

View File

@ -103,7 +103,7 @@ int verb_enable(int argc, char *argv[], void *userdata) {
/* If the operation was fully executed by the SysV compat, let's finish early */
if (strv_isempty(names)) {
if (arg_no_reload || install_client_side())
if (arg_no_reload || install_client_side() != INSTALL_CLIENT_SIDE_NO)
return 0;
r = daemon_reload(ACTION_RELOAD, /* graceful= */ false);
@ -119,41 +119,7 @@ int verb_enable(int argc, char *argv[], void *userdata) {
if (r < 0)
return r;
if (install_client_side()) {
UnitFileFlags flags;
InstallChange *changes = NULL;
size_t n_changes = 0;
CLEANUP_ARRAY(changes, n_changes, install_changes_free);
flags = unit_file_flags_from_args();
if (streq(verb, "enable")) {
r = unit_file_enable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
carries_install_info = r;
} else if (streq(verb, "disable")) {
r = unit_file_disable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
carries_install_info = r;
} else if (streq(verb, "reenable")) {
r = unit_file_reenable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
carries_install_info = r;
} else if (streq(verb, "link"))
r = unit_file_link(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
else if (streq(verb, "preset"))
r = unit_file_preset(arg_runtime_scope, flags, arg_root, names, arg_preset_mode, &changes, &n_changes);
else if (streq(verb, "mask"))
r = unit_file_mask(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
else if (streq(verb, "unmask"))
r = unit_file_unmask(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
else if (streq(verb, "revert"))
r = unit_file_revert(arg_runtime_scope, arg_root, names, &changes, &n_changes);
else
assert_not_reached();
install_changes_dump(r, verb, changes, n_changes, arg_quiet);
if (r < 0)
return r;
} else {
if (install_client_side() == INSTALL_CLIENT_SIDE_NO) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
bool expect_carries_install_info = false;
@ -275,6 +241,40 @@ int verb_enable(int argc, char *argv[], void *userdata) {
if (warn_trigger_operation && !arg_quiet && !arg_no_warn)
STRV_FOREACH(unit, names)
warn_triggering_units(bus, *unit, warn_trigger_operation, warn_trigger_ignore_masked);
} else {
UnitFileFlags flags;
InstallChange *changes = NULL;
size_t n_changes = 0;
CLEANUP_ARRAY(changes, n_changes, install_changes_free);
flags = unit_file_flags_from_args();
if (streq(verb, "enable")) {
r = unit_file_enable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
carries_install_info = r;
} else if (streq(verb, "disable")) {
r = unit_file_disable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
carries_install_info = r;
} else if (streq(verb, "reenable")) {
r = unit_file_reenable(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
carries_install_info = r;
} else if (streq(verb, "link"))
r = unit_file_link(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
else if (streq(verb, "preset"))
r = unit_file_preset(arg_runtime_scope, flags, arg_root, names, arg_preset_mode, &changes, &n_changes);
else if (streq(verb, "mask"))
r = unit_file_mask(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
else if (streq(verb, "unmask"))
r = unit_file_unmask(arg_runtime_scope, flags, arg_root, names, &changes, &n_changes);
else if (streq(verb, "revert"))
r = unit_file_revert(arg_runtime_scope, arg_root, names, &changes, &n_changes);
else
assert_not_reached();
install_changes_dump(r, verb, changes, n_changes, arg_quiet);
if (r < 0)
return r;
}
if (carries_install_info == 0 && !ignore_carries_install_info)
@ -334,7 +334,7 @@ int verb_enable(int argc, char *argv[], void *userdata) {
if (arg_now) {
_cleanup_strv_free_ char **new_args = NULL;
const char *start_verb;
bool accept_path, prohibit_templates;
bool accept_path, prohibit_templates, dead_ok = false;
if (streq(verb, "enable")) {
start_verb = "start";
@ -344,6 +344,7 @@ int verb_enable(int argc, char *argv[], void *userdata) {
start_verb = "stop";
accept_path = false;
prohibit_templates = false;
dead_ok = true; /* If the service is not running anyway, no need to stop it. */
} else if (streq(verb, "reenable")) {
/* Note that we use try-restart here. This matches the semantics of reenable better,
* and allows us to glob template units. */
@ -354,9 +355,20 @@ int verb_enable(int argc, char *argv[], void *userdata) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"--now can only be used with verb enable, disable, reenable, or mask.");
if (install_client_side())
return log_error_errno(SYNTHETIC_ERRNO(EREMOTE),
"--now cannot be used when systemd is not running or in conjunction with --root=/--global, refusing.");
switch (install_client_side()) {
case INSTALL_CLIENT_SIDE_NO:
break;
case INSTALL_CLIENT_SIDE_OVERRIDE:
case INSTALL_CLIENT_SIDE_OFFLINE:
case INSTALL_CLIENT_SIDE_NOT_BOOTED:
if (!dead_ok)
log_warning("Cannot %s unit with --now when systemd is not running, ignoring.", start_verb);
return 0;
case INSTALL_CLIENT_SIDE_ARG_ROOT:
return log_error_errno(SYNTHETIC_ERRNO(EREMOTE), "--now cannot be used with --root=.");
case INSTALL_CLIENT_SIDE_GLOBAL_SCOPE:
return log_error_errno(SYNTHETIC_ERRNO(EREMOTE), "--now cannot be used with --global.");
}
assert(bus);

View File

@ -82,7 +82,7 @@ int verb_is_enabled(int argc, char *argv[], void *userdata) {
not_found = r == 0; /* Doesn't have SysV support or SYSV_UNIT_NOT_FOUND */
enabled = r == SYSV_UNIT_ENABLED;
if (install_client_side())
if (install_client_side() != INSTALL_CLIENT_SIDE_NO)
STRV_FOREACH(name, names) {
UnitFileState state;

View File

@ -180,7 +180,7 @@ int verb_list_unit_files(int argc, char *argv[], void *userdata) {
unsigned c = 0;
int r;
if (install_client_side()) {
if (install_client_side() != INSTALL_CLIENT_SIDE_NO) {
unsigned n_units;
r = unit_file_get_list(arg_runtime_scope, arg_root, arg_states, strv_skip(argv, 1), &h);

View File

@ -19,7 +19,7 @@ int verb_preset_all(int argc, char *argv[], void *userdata) {
if (should_bypass("SYSTEMD_PRESET"))
return 0;
if (install_client_side()) {
if (install_client_side() != INSTALL_CLIENT_SIDE_NO) {
InstallChange *changes = NULL;
size_t n_changes = 0;

View File

@ -58,7 +58,7 @@ static void emit_cmdline_warning(void) {
static int determine_default(char **ret_name) {
int r;
if (install_client_side()) {
if (install_client_side() != INSTALL_CLIENT_SIDE_NO) {
r = unit_file_get_default(arg_runtime_scope, arg_root, ret_name);
if (r == -ERFKILL)
return log_error_errno(r, "Failed to get default target: Unit file is masked.");
@ -116,7 +116,7 @@ int verb_set_default(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to mangle unit name: %m");
if (install_client_side()) {
if (install_client_side() != INSTALL_CLIENT_SIDE_NO) {
InstallChange *changes = NULL;
size_t n_changes = 0;

View File

@ -523,7 +523,7 @@ int unit_find_paths(
/* Go via the bus to acquire the path, unless we are explicitly told not to, or when the unit name is a template */
if (!force_client_side &&
!install_client_side() &&
install_client_side() == INSTALL_CLIENT_SIDE_NO &&
!unit_name_is_valid(unit_name, UNIT_NAME_TEMPLATE)) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_free_ char *load_state = NULL, *dbus_path = NULL;
@ -880,26 +880,27 @@ bool output_show_unit(const UnitInfo *u, char **patterns) {
return true;
}
bool install_client_side(void) {
/* Decides when to execute enable/disable/... operations client-side rather than server-side. */
if (running_in_chroot_or_offline())
return true;
if (sd_booted() <= 0)
return true;
if (!isempty(arg_root))
return true;
if (arg_runtime_scope == RUNTIME_SCOPE_GLOBAL)
return true;
InstallClientSide install_client_side(void) {
/* Decides whether to execute enable/disable/… client-side offline operation rather than
* server-side. */
/* Unsupported environment variable, mostly for debugging purposes */
if (getenv_bool("SYSTEMCTL_INSTALL_CLIENT_SIDE") > 0)
return true;
return INSTALL_CLIENT_SIDE_OVERRIDE;
return false;
if (!isempty(arg_root))
return INSTALL_CLIENT_SIDE_ARG_ROOT;
if (running_in_chroot_or_offline())
return INSTALL_CLIENT_SIDE_OFFLINE;
if (sd_booted() <= 0)
return INSTALL_CLIENT_SIDE_NOT_BOOTED;
if (arg_runtime_scope == RUNTIME_SCOPE_GLOBAL)
return INSTALL_CLIENT_SIDE_GLOBAL_SCOPE;
return INSTALL_CLIENT_SIDE_NO;
}
int output_table(Table *table) {

View File

@ -69,7 +69,16 @@ int unit_get_dependencies(sd_bus *bus, const char *name, char ***ret);
const char* unit_type_suffix(const char *unit);
bool output_show_unit(const UnitInfo *u, char **patterns);
bool install_client_side(void);
typedef enum InstallClientSide {
INSTALL_CLIENT_SIDE_NO = 0,
INSTALL_CLIENT_SIDE_OVERRIDE,
INSTALL_CLIENT_SIDE_ARG_ROOT,
INSTALL_CLIENT_SIDE_OFFLINE,
INSTALL_CLIENT_SIDE_NOT_BOOTED,
INSTALL_CLIENT_SIDE_GLOBAL_SCOPE,
} InstallClientSide;
InstallClientSide install_client_side(void);
int output_table(Table *table);

View File

@ -445,8 +445,8 @@ def main() -> None:
summary = Summary.get(args)
# Keep list in sync with TEST-06-SELINUX.sh
if args.name == 'TEST-06-SELINUX' and summary.distribution not in ('fedora', 'centos'):
print('Skipping TEST-06-SELINUX, only enabled for Fedora/CentOS', file=sys.stderr)
if args.name == 'TEST-06-SELINUX' and summary.distribution not in ('centos', 'fedora', 'opensuse'):
print('Skipping TEST-06-SELINUX, only enabled for CentOS/Fedora/openSUSE', file=sys.stderr)
exit(77)
if shell and not sys.stdin.isatty():

View File

@ -81,10 +81,10 @@ valgrind_cmd = ''
enable_debug = True
env = {}
wait_online_env = {}
asan_options = None
lsan_options = None
ubsan_options = None
with_coverage = False
asan_options = os.getenv('ASAN_OPTIONS')
lsan_options = os.getenv('LSAN_OPTIONS')
ubsan_options = os.getenv('UBSAN_OPTIONS')
with_coverage = os.getenv('COVERAGE_BUILD_DIR') != None
show_journal = True # When true, show journal on stopping networkd.
active_units = []
@ -487,7 +487,19 @@ def create_service_dropin(service, command, additional_settings=None):
if ubsan_options:
drop_in += [f'Environment=UBSAN_OPTIONS="{ubsan_options}"']
if asan_options or lsan_options or ubsan_options:
drop_in += ['SystemCallFilter=']
# Disable system call filter when running with sanitizers, as they seem to call filtered syscall at
# the very end of the execution and stuck the process. See issue #39567.
drop_in += [
'LockPersonality=no',
'ProtectClock=no',
'ProtectKernelLogs=no',
'RestrictAddressFamilies=',
'RestrictNamespaces=no',
'RestrictRealtime=no',
'RestrictSUIDSGID=no',
'SystemCallArchitectures=',
'SystemCallFilter=',
]
if use_valgrind or asan_options or lsan_options or ubsan_options:
drop_in += ['MemoryDenyWriteExecute=no']
if use_valgrind:

View File

@ -104,10 +104,12 @@ diff /tmp/expected /tmp/output
# test that LogLevelMax can also suppress logging about services, not only by services
systemctl start silent-success
journalctl --sync
[[ -z "$(journalctl -b -q -u silent-success.service)" ]]
# Test syslog identifiers exclusion
systemctl start verbose-success.service
journalctl --sync
[[ -n "$(journalctl -b -q -u verbose-success.service -t systemd)" ]]
[[ -n "$(journalctl -b -q -u verbose-success.service -t bash)" ]]
[[ -n "$(journalctl -b -q -u verbose-success.service -T systemd)" ]]

View File

@ -4,8 +4,8 @@ set -eux
set -o pipefail
. /etc/os-release
if ! [[ "$ID" =~ centos|fedora ]]; then
echo "Skipping because only CentOS and Fedora support SELinux tests" >>/skipped
if ! [[ "$ID" =~ centos|fedora|opensuse ]]; then
echo "Skipping because only CentOS, Fedora and openSUSE support SELinux tests" >>/skipped
exit 77
fi

View File

@ -72,7 +72,7 @@ assert_eq "$(systemctl show "$UNIT_NAME.socket" -P SubState)" "listening"
socat -u - UNIX-CONNECT:"/tmp/$UNIT_NAME/test" &
wait_for_start
kill %%
wait %%
touch "/tmp/$UNIT_NAME/flag"
systemctl start "$UNIT_NAME-conflict2.service"
@ -80,7 +80,7 @@ wait_for_stop
socat -u - UNIX-CONNECT:"/tmp/$UNIT_NAME/test" &
wait_for_start
kill %%
wait %%
(! systemctl -q is-active "$UNIT_NAME-conflict2.service")
# DeferTrigger=yes
@ -99,7 +99,7 @@ assert_eq "$(systemctl show "$UNIT_NAME-conflict1.service" -P SubState)" "start"
socat -u - UNIX-CONNECT:"/tmp/$UNIT_NAME/test" &
timeout 30 bash -c "until [[ \$(systemctl show '$UNIT_NAME.socket' -P SubState) == 'deferred' ]]; do sleep .5; done"
(! systemctl -q is-active "$UNIT_NAME.service")
kill %%
wait %%
assert_eq "$(systemctl show "$UNIT_NAME-conflict1.service" -P SubState)" "start"
systemctl daemon-reload
@ -122,7 +122,7 @@ wait_for_stop
socat -u - UNIX-CONNECT:"/tmp/$UNIT_NAME/test" &
timeout 30 bash -c "until [[ \$(systemctl show '$UNIT_NAME.socket' -P SubState) == 'deferred' ]]; do sleep .5; done"
(! systemctl -q is-active "$UNIT_NAME.service")
kill %%
wait %%
rm "/tmp/$UNIT_NAME/flag"
timeout 30 bash -c "while systemctl -q is-active '$UNIT_NAME-conflict2.service'; do sleep .2; done"
@ -138,7 +138,7 @@ assert_eq "$(systemctl show "$UNIT_NAME-conflict1.service" -P SubState)" "start"
socat -u - UNIX-CONNECT:"/tmp/$UNIT_NAME/test" &
timeout 30 bash -c "until [[ \$(systemctl show '$UNIT_NAME.socket' -P SubState) == 'deferred' ]]; do sleep .5; done"
(! systemctl -q is-active "$UNIT_NAME.service")
kill %%
wait %%
echo "DeferTriggerMaxSec=20s" >>/run/systemd/system/"$UNIT_NAME.socket"
systemctl daemon-reload

View File

@ -50,6 +50,7 @@ trap 'touch /terminate; kill 0' RTMIN+3
trap 'touch /poweroff' RTMIN+4
trap 'touch /reboot' INT
trap 'touch /trap' TRAP
trap 'exit 0' TERM
trap 'kill $PID' EXIT
# We need to wait for the sleep process asynchronously in order to allow
@ -327,6 +328,7 @@ ip address add 192.0.2.1/24 dev hoge
PID=0
trap 'kill 0' RTMIN+3
trap 'exit 0' TERM
trap 'kill $PID' EXIT
# We need to wait for the sleep process asynchronously in order to allow
@ -441,9 +443,14 @@ varlinkctl call /run/systemd/machine/io.systemd.Machine io.systemd.Machine.OpenR
# Terminating machine, otherwise acquiring image metadata by io.systemd.MachineImage.List may fail in the below.
machinectl terminate long-running
# wait for the container being stopped, otherwise acquiring image metadata by io.systemd.MachineImage.List may fail in the below.
timeout 30 bash -c "while machinectl status long-running &>/dev/null; do sleep .5; done"
systemctl kill --signal=KILL systemd-nspawn@long-running.service || :
# Wait for the container to stop, otherwise acquiring image metadata by io.systemd.MachineImage.List below
# may fail.
#
# We need to wait until the systemd-nspawn process is completely stopped, as the lock is held for almost the
# entire life of the process (see the run() function in nspawn.c). This means that the machine gets
# unregistered _before_ this lock is lifted which makes `machinectl status` return non-zero EC earlier than
# we need.
timeout 30 bash -xec 'until [[ "$(systemctl show -P ActiveState systemd-nspawn@long-running.service)" == inactive ]]; do sleep .5; done'
# test io.systemd.MachineImage.List
varlinkctl --more call /run/systemd/machine/io.systemd.MachineImage io.systemd.MachineImage.List '{}' | grep 'long-running'

View File

@ -9,18 +9,6 @@ set -o pipefail
# shellcheck source=test/units/util.sh
. "$(dirname "$0")"/util.sh
# Requires kernel built with certain kconfigs, as listed in README:
# https://oracle.github.io/kconfigs/?config=UTS_RELEASE&config=DM_VERITY_VERIFY_ROOTHASH_SIG&config=DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING&config=DM_VERITY_VERIFY_ROOTHASH_SIG_PLATFORM_KEYRING&config=IMA_ARCH_POLICY&config=INTEGRITY_MACHINE_KEYRING
if grep -q "$(openssl x509 -noout -subject -in /usr/share/mkosi.crt | sed 's/^.*CN=//')" /proc/keys && \
( . /etc/os-release; [ "$ID" != "centos" ] || systemd-analyze compare-versions "$VERSION_ID" ge 10 ) && \
( . /etc/os-release; [ "$ID" != "debian" ] || systemd-analyze compare-versions "$VERSION_ID" ge 13 ) && \
( . /etc/os-release; [ "$ID" != "ubuntu" ] || systemd-analyze compare-versions "$VERSION_ID" ge 24.04 ) && \
systemd-analyze compare-versions "$(cryptsetup --version | sed 's/^cryptsetup \([0-9]*\.[0-9]*\.[0-9]*\) .*/\1/')" ge 2.3.0; then
verity_sig_supported=1
else
verity_sig_supported=0
fi
systemd-dissect --json=short "$MINIMAL_IMAGE.raw" | \
grep -q -F '{"rw":"ro","designator":"root","partition_uuid":null,"partition_label":null,"fstype":"squashfs","architecture":null,"verity":"external"'
systemd-dissect "$MINIMAL_IMAGE.raw" | grep -q -F "MARKER=1"
@ -84,7 +72,7 @@ if [[ "$verity_count" -lt 1 ]]; then
exit 1
fi
# Ensure the kernel is verifying the signature if the mkosi key is in the keyring
if [ "$verity_sig_supported" -eq 1 ]; then
if [ "$VERITY_SIG_SUPPORTED" -eq 1 ]; then
veritysetup status "$(cat "$MINIMAL_IMAGE.roothash")-verity" | grep -q "verified (with signature)"
fi
systemd-dissect --umount "$IMAGE_DIR/mount"
@ -472,8 +460,8 @@ RootImage=$MINIMAL_IMAGE.raw
ExtensionImages=/tmp/app0.raw /tmp/app1.raw:nosuid
# Relevant only for sanitizer runs
UnsetEnvironment=LD_PRELOAD
ExecStart=bash -c '/opt/script0.sh | grep ID'
ExecStart=bash -c '/opt/script1.sh | grep ID'
ExecStart=bash -o pipefail -c '/opt/script0.sh | grep ID'
ExecStart=bash -o pipefail -c '/opt/script1.sh | grep ID'
Type=oneshot
RemainAfterExit=yes
EOF
@ -490,7 +478,7 @@ mkdir "$VDIR" "$EMPTY_VDIR"
ln -s /tmp/app0.raw "$VDIR/${VBASE}_0.raw"
ln -s /tmp/app1.raw "$VDIR/${VBASE}_1.raw"
systemd-run -P -p ExtensionImages="$VDIR -$EMPTY_VDIR -$NONEXISTENT_VDIR" bash -c '/opt/script1.sh | grep ID'
systemd-run -P -p ExtensionImages="$VDIR -$EMPTY_VDIR -$NONEXISTENT_VDIR" bash -o pipefail -c '/opt/script1.sh | grep ID'
rm -rf "$VDIR" "$EMPTY_VDIR"
@ -587,7 +575,7 @@ EnvironmentFile=-/usr/lib/systemd/systemd-asan-env
PrivateTmp=disconnected
BindPaths=/tmp/markers/
ExtensionDirectories=-${VDIR}
ExecStart=bash -x -c ' \\
ExecStart=bash -o pipefail -x -c ' \\
trap "{ \\
systemd-notify --reloading; \\
(ls /etc | grep marker || echo no-marker) >/tmp/markers/50g; \\
@ -628,7 +616,7 @@ EnvironmentFile=-/usr/lib/systemd/systemd-asan-env
PrivateTmp=disconnected
BindPaths=/tmp/markers/
ExtensionImages=-$VDIR2
ExecStart=bash -x -c ' \\
ExecStart=bash -o pipefail -x -c ' \\
trap "{ \\
systemd-notify --reloading; \\
(ls /etc | grep marker || echo no-marker) >/tmp/markers/50h; \\
@ -666,7 +654,7 @@ BindPaths=/tmp/markers/
RootImage=$MINIMAL_IMAGE.raw
ExtensionDirectories=-${VDIR}
NotifyAccess=all
ExecStart=bash -x -c ' \
ExecStart=bash -x -o pipefail -c ' \
trap '"'"' \
now=\$\$(grep "^now" /proc/timer_list | cut -d" " -f3 | rev | cut -c 4- | rev); \
stdbuf -o1K printf "RELOADING=1\\nMONOTONIC_USEC=\$\${now}\\n" | socat -t 5 - UNIX-SENDTO:\$\$NOTIFY_SOCKET; \
@ -701,7 +689,7 @@ BindPaths=/tmp/markers/
RootDirectory=/tmp/vpickminimg
ExtensionDirectories=-${VDIR}
NotifyAccess=all
ExecStart=bash -x -c ' \
ExecStart=bash -x -o pipefail -c ' \
trap '"'"' \
now=\$\$(grep "^now" /proc/timer_list | cut -d" " -f3 | rev | cut -c 4- | rev); \
stdbuf -o1K printf "RELOADING=1\\nMONOTONIC_USEC=\$\${now}\\n" | socat -t 5 - UNIX-SENDTO:\$\$NOTIFY_SOCKET; \
@ -731,7 +719,7 @@ RootImage=$MINIMAL_IMAGE.raw
ExtensionImages=-$VDIR2 /tmp/app0.raw
PrivateUsers=yes
NotifyAccess=all
ExecStart=bash -x -c ' \
ExecStart=bash -x -o pipefail -c ' \
trap '"'"' \
now=\$\$(grep "^now" /proc/timer_list | cut -d" " -f3 | rev | cut -c 4- | rev); \
stdbuf -o1K printf "RELOADING=1\\nMONOTONIC_USEC=\$\${now}\\n" | socat -t 5 - UNIX-SENDTO:\$\$NOTIFY_SOCKET; \
@ -746,7 +734,7 @@ EOF
systemctl start testservice-50k.service
systemctl is-active testservice-50k.service
# Ensure the kernel is verifying the signature if the mkosi key is in the keyring
if [ "$verity_sig_supported" -eq 1 ]; then
if [ "$VERITY_SIG_SUPPORTED" -eq 1 ]; then
veritysetup status "$(cat "$MINIMAL_IMAGE.roothash")-verity" | grep -q "verified (with signature)"
fi
# First reload should pick up the v1 marker

View File

@ -25,10 +25,27 @@ at_exit() {
done < <(find "${IMAGE_DIR}" -mindepth 1 -maxdepth 1 -type d)
rm -rf "$IMAGE_DIR"
loginctl disable-linger testuser
}
trap at_exit EXIT
# For unprivileged tests
loginctl enable-linger testuser
# Requires kernel built with certain kconfigs, as listed in README:
# https://oracle.github.io/kconfigs/?config=UTS_RELEASE&config=DM_VERITY_VERIFY_ROOTHASH_SIG&config=DM_VERITY_VERIFY_ROOTHASH_SIG_SECONDARY_KEYRING&config=DM_VERITY_VERIFY_ROOTHASH_SIG_PLATFORM_KEYRING&config=IMA_ARCH_POLICY&config=INTEGRITY_MACHINE_KEYRING
if grep -q "$(openssl x509 -noout -subject -in /usr/share/mkosi.crt | sed 's/^.*CN=//')" /proc/keys && \
( . /etc/os-release; [ "$ID" != "centos" ] || systemd-analyze compare-versions "$VERSION_ID" ge 10 ) && \
( . /etc/os-release; [ "$ID" != "debian" ] || [ -z "${VERSION_ID:-}" ] || systemd-analyze compare-versions "$VERSION_ID" ge 13 ) && \
( . /etc/os-release; [ "$ID" != "ubuntu" ] || systemd-analyze compare-versions "$VERSION_ID" ge 24.04 ) && \
systemd-analyze compare-versions "$(cryptsetup --version | sed 's/^cryptsetup \([0-9]*\.[0-9]*\.[0-9]*\) .*/\1/')" ge 2.3.0; then
export VERITY_SIG_SUPPORTED=1
else
export VERITY_SIG_SUPPORTED=0
fi
: "Setup base images"
export SYSTEMD_LOG_LEVEL=debug
@ -102,6 +119,7 @@ fi
udevadm control --log-level=debug
IMAGE_DIR="$(mktemp -d --tmpdir="" TEST-50-IMAGES.XXX)"
chmod go+rx "$IMAGE_DIR"
cp -v /usr/share/minimal* "$IMAGE_DIR/"
MINIMAL_IMAGE="$IMAGE_DIR/minimal_0"
MINIMAL_IMAGE_ROOTHASH="$(<"$MINIMAL_IMAGE.roothash")"

View File

@ -1064,10 +1064,13 @@ extension_verify_after_unmerge "$fake_root" "$hierarchy" -h
fake_root=${roots_dir:+"$roots_dir/mutable-directory-with-invalid-permissions"}
hierarchy=/opt
extension_data_dir="$fake_root/var/lib/extensions.mutable$hierarchy"
extension_data_dir_usr="$fake_root/var/lib/extensions.mutable/usr"
prepare_root "$fake_root" "$hierarchy"
prepare_extension_image "$fake_root" "$hierarchy"
prepare_extension_mutable_dir "$extension_data_dir"
prepend_trap "rm -rf ${extension_data_dir@Q}"
prepend_trap "rm -rf ${extension_data_dir_usr@Q}"
prepare_hierarchy "$fake_root" "$hierarchy"
old_mode=$(stat --format '%#a' "$fake_root$hierarchy")
@ -1078,6 +1081,29 @@ chmod 0700 "$extension_data_dir"
(! run_systemd_sysext "$fake_root" --mutable=yes merge)
)
( init_trap
: "Check if merging fails in case of --root= being an initrd but the extension is not for it"
# Since this is really about whether --root= gets prepended for the /etc/initrd-release check,
# this also tests the more interesting reverse case that we are in the initrd and prepare
# the mounts for the final system with --root=/sysroot
fake_root=${roots_dir:+"$roots_dir/initrd-env-with-non-initrd-extension"}
hierarchy=/opt
prepare_root "$fake_root" "$hierarchy"
prepare_extension_image "$fake_root" "$hierarchy"
mkdir -p "${fake_root}/etc"
touch "${fake_root}/etc/initrd-release"
prepare_read_only_hierarchy "$fake_root" "$hierarchy"
# Should be a no-op, thus we also don't run unmerge afterwards (otherwise the test is broken)
run_systemd_sysext "$fake_root" merge
if run_systemd_sysext "$fake_root" status --json=pretty | jq -r '.[].extensions' | grep -v '^none$' ; then
echo >&2 "Extension got loaded for an initrd structure passed as --root= while the extension does not declare itself compatible with the initrd scope"
exit 1
fi
rm "${fake_root}/etc/initrd-release"
)
} # End of run_sysext_tests

View File

@ -15,11 +15,11 @@ set -o pipefail
. "$(dirname "$0")"/util.sh
UNIT_NAME="timer-RandomizedDelaySec-$RANDOM"
TARGET_TS="$(date --date="tomorrow 00:10")"
TARGET_TS="$(date --date="tomorrow 00:10" "+%a %Y-%m-%d %H:%M:%S %Z")"
TARGET_TS_S="$(date --date="$TARGET_TS" "+%s")"
# Maximum possible next elapse timestamp: $TARGET_TS (OnCalendar=) + 22 hours (RandomizedDelaySec=)
MAX_NEXT_ELAPSE_REALTIME_S="$((TARGET_TS_S + 22 * 60 * 60))"
MAX_NEXT_ELAPSE_REALTIME="$(date --date="@$MAX_NEXT_ELAPSE_REALTIME_S")"
MAX_NEXT_ELAPSE_REALTIME="$(date --date="@$MAX_NEXT_ELAPSE_REALTIME_S" "+%a %Y-%m-%d %H:%M:%S %Z")"
# Let's make sure to return the date & time back to the original state once we're done with our time
# shenigans. One way to do this would be to use hwclock, but the RTC in VMs can be unreliable or slow to

View File

@ -19,7 +19,7 @@ systemd-analyze time || :
systemd-analyze critical-chain || :
# blame
systemd-analyze blame
systemd-run --wait --user --pipe -M testuser@.host systemd-analyze blame
systemd-run --wait --user --pipe -M testuser@.host systemd-analyze blame --no-pager
(! systemd-analyze blame --global)
# plot
systemd-analyze plot >/dev/null || :

View File

@ -15,7 +15,7 @@ fi
"$SD_TPM2SETUP" --version
"$SD_TPM2SETUP" --tpm2-device=list
"$SD_TPM2SETUP" --tpm2-device=auto
"$SD_TPM2SETUP" --tpm2-device=/dev/tpm0
"$SD_TPM2SETUP" --tpm2-device=/dev/tpmrm0
"$SD_TPM2SETUP" --early=yes
"$SD_TPM2SETUP" --early=yes
"$SD_TPM2SETUP" --early=no

View File

@ -81,6 +81,11 @@ systemd-run --wait --pipe --user --machine=testuser@ \
systemd-run --wait --pipe --user --machine=testuser@ \
bash -xec '[[ "$PWD" == /home/testuser && -n "$INVOCATION_ID" ]]'
# https://github.com/systemd/systemd/issues/39038
systemd-run --wait --machine=testuser@ --user -p User=testuser true
systemd-run --wait --machine=testuser@ --user -p Group=testuser true
(! systemd-run --wait --machine=testuser@ --user -p Group=testuser -p SupplementaryGroups=root true)
# PrivateTmp=yes implies PrivateUsers=yes for user manager, so skip this if we
# don't have unprivileged user namespaces.
if [[ "$(sysctl -ne kernel.apparmor_restrict_unprivileged_userns)" -ne 1 ]]; then

View File

@ -11,7 +11,7 @@ assert_in systemd-socket "$(cat /proc/"$PID"/comm)"
assert_eq "$(echo -n hello | socat - 'TCP:localhost:1234')" hello
assert_in systemd-socket "$(cat /proc/"$PID"/comm)"
kill "$PID"
wait "$PID" || :
tail --pid="$PID" -f /dev/null
PID=$(systemd-notify --fork -- systemd-socket-activate -l 1234 --now socat ACCEPT-FD:3 PIPE)
for _ in {1..100}; do
@ -24,7 +24,7 @@ for _ in {1..100}; do
if [[ "$(cat /proc/"$PID"/comm || :)" =~ socat ]]; then
assert_eq "$(echo -n bye | socat - 'TCP:localhost:1234')" bye
wait "$PID" || :
tail --pid="$PID" -f /dev/null
break
fi
done

View File

@ -64,11 +64,13 @@ monitor_check_rr() (
)
restart_resolved() {
systemctl stop systemd-resolved-monitor.socket systemd-resolved-varlink.socket
systemctl stop systemd-resolved.service
(! systemctl is-failed systemd-resolved.service)
# Reset the restart counter since we call this method a bunch of times
# and can occasionally hit the default rate limit
systemctl reset-failed systemd-resolved.service
systemctl start systemd-resolved-monitor.socket systemd-resolved-varlink.socket
systemctl start systemd-resolved.service
systemctl service-log-level systemd-resolved.service debug
}
@ -183,8 +185,8 @@ EOF
chown -R knot:knot /run/knot
fi
systemctl start knot
# Wait a bit for the keys to propagate
sleep 4
# Wait for signed.test's zone DS records to get pushed to the parent zone
timeout 30s bash -xec 'until knotc zone-read test. signed.test. ds | grep -E "signed\.test\. [0-9]+ DS"; do sleep 2; done'
systemctl status resolved-dummy-server
networkctl status
@ -334,6 +336,7 @@ manual_testcase_02_mdns_llmnr() {
} >/run/systemd/resolved.conf.d/90-mdns-llmnr.conf
restart_resolved
# make sure networkd is not running.
systemctl stop systemd-networkd.socket systemd-networkd-varlink.socket
systemctl stop systemd-networkd.service
assert_in 'no' "$(resolvectl mdns hoge)"
assert_in 'no' "$(resolvectl llmnr hoge)"
@ -1368,7 +1371,9 @@ testcase_15_wait_online_dns() {
resolvectl domain dns0 ""
# Stop systemd-resolved before calling systemd-networkd-wait-online. It should retry connections.
systemctl stop systemd-resolved-monitor.socket systemd-resolved-varlink.socket
systemctl stop systemd-resolved.service
systemctl start systemd-resolved-monitor.socket systemd-resolved-varlink.socket
# Begin systemd-networkd-wait-online --dns
systemd-run -u "$unit" -p "Environment=SYSTEMD_LOG_LEVEL=debug" -p "Environment=SYSTEMD_LOG_TARGET=journal" --service-type=exec \

View File

@ -342,7 +342,8 @@ EOF
bootctl remove
}
testcase_secureboot() {
# Order this first, as other test cases mess with the ESP and might break 'bootctl status' output
testcase_00_secureboot() {
if [ ! -d /sys/firmware/efi ]; then
echo "Not booted with EFI, skipping secureboot tests."
return 0

View File

@ -163,7 +163,7 @@ rm -f /tmp/core.{output,redirected}
# Unprivileged stuff
# Related issue: https://github.com/systemd/systemd/issues/26912
UNPRIV_CMD=(systemd-run --user --wait --pipe -M "testuser@.host" --)
UNPRIV_CMD=(systemd-run --user --wait --pipe -M "testuser@.host" -E SYSTEMD_PAGER --)
# Trigger a couple of coredumps as an unprivileged user
"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGTRAP"
"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGABRT"

View File

@ -3,11 +3,11 @@
set -eux
set -o pipefail
(! journalctl -q -o short-monotonic --grep "didn't pass validation" | grep -v "test-varlink-idl" >>/failed)
(! journalctl -q -o short-monotonic --grep "didn't pass validation" | grep -v "test-varlink-idl")
# Here, the redundant '[ ]' in the pattern is required in order not to match the logged command itself.
(! journalctl -q -o short-monotonic --grep 'Warning: cannot close sd-bus connection[ ].*after fork' >>/failed)
(! journalctl -q -o short-monotonic --grep 'Warning: cannot close sd-bus connection[ ].*after fork')
# Check if sd-executor doesn't complain about not being able to (de)serialize stuff
(! journalctl -q -o short-monotonic --grep "[F]ailed to parse serialized line" >>/failed)
(! journalctl -q -o short-monotonic --grep "[F]ailed to (de)?serialize \w+" >>/failed)
(! journalctl -q -o short-monotonic --grep "[F]ailed to parse serialized line")
(! journalctl -q -o short-monotonic --grep "[F]ailed to (de)?serialize \w+")

View File

@ -323,6 +323,13 @@ EOF
echo MARKER=1 >"$initdir/usr/lib/systemd/system/some_file"
mksquashfs "$initdir" /tmp/app0.raw -noappend
veritysetup format /tmp/app0.raw /tmp/app0.verity --root-hash-file /tmp/app0.roothash
openssl smime -sign -nocerts -noattr -binary \
-in /tmp/app0.roothash \
-inkey /usr/share/mkosi.key \
-signer /usr/share/mkosi.crt \
-outform der \
-out /tmp/app0.roothash.p7s
chmod go+r /tmp/app0*
initdir="/var/tmp/conf0"
mkdir -p "$initdir/etc/extension-release.d" "$initdir/etc/systemd/system" "$initdir/opt"
@ -335,6 +342,13 @@ EOF
echo MARKER_1 >"$initdir/etc/systemd/system/some_file"
mksquashfs "$initdir" /tmp/conf0.raw -noappend
veritysetup format /tmp/conf0.raw /tmp/conf0.verity --root-hash-file /tmp/conf0.roothash
openssl smime -sign -nocerts -noattr -binary \
-in /tmp/conf0.roothash \
-inkey /usr/share/mkosi.key \
-signer /usr/share/mkosi.crt \
-outform der \
-out /tmp/conf0.roothash.p7s
chmod go+r /tmp/conf0*
initdir="/var/tmp/app1"
mkdir -p "$initdir/usr/lib/extension-release.d" "$initdir/usr/lib/systemd/system" "$initdir/opt"

View File

@ -8,7 +8,7 @@
# (at your option) any later version.
[Unit]
Description=Generate network units from Kernel command line
Description=Generate Network Units from Kernel Command Line
Documentation=man:systemd-network-generator.service(8)
DefaultDependencies=no