The previous x2 was still not enough, and the test is still killed often in
slow GHA CI workers, eg:
https://github.com/systemd/systemd/actions/runs/28012425459/job/82908555094?pr=42705
This happens in test units with many commands, so reset the timer when
a command completes and the test advances. The number of Exec
instructions is bounded so this will terminate jobs that are really
stuck anyway.
Follow-up for 3b00327fe6
The test is flaky and times out lately in ppc64el CI runners:
exec-dynamicuser-statedir.service: Control group is empty.
exec-dynamicuser-statedir.service: User lookup succeeded: uid=65325 gid=65325
Test timeout when testing exec-dynamicuser-statedir.service
Bump the timeout also when in a CI, as they are often over subscribed
In order to allow FD Stores of user units to survive a user
session restart, propagate FDs received via the protocol up one
level from user to system manager via sd_notify.
And the other way around, propagate them down via LISTEN_FDS
tagging them with the unit name so that the child manager can
inject them in the appropriate unit.
Ensure units that are dead or not loaded can get FDs added to
their stores, and that they are correctly propagated once the
unit is started or loaded. When the unit is not loaded we don't
know what the FD max limit is, so simply increase it for each FD
injected, and then when the unit is realised prune it down to
match the unit's now available config in case the limit is lower
than the number of FDs in the store.
Each FD sent up or down is assigned a monotonic index, and the manager
also sends a JSON map that associates the index with the original
unit and FDNAME:
{
"unit-name.service": [
{ "name": "fdname1", "index": 1 },
{ "name": "fdname2", "index": 2 }
],
...
}
This allows the manager to assign back the FDs to the appropriate
unit using the appropriate name, given the FDNAMEs are not unique.
Every dlopen_xxx() helper now takes an int log_level argument. It is
passed through to dlopen_many_sym_or_warn() (which in turn propagates it
to dlopen_verbose() for the library-not-installed case), and is used by
the fallback stub when support for the library is not compiled in to
emit a "<lib> support is not compiled in." message at the caller's level.
Callers pass LOG_DEBUG when gracefully degrading, or a higher level when
the failure should surface, and no longer need to log redundantly at the
call site.
As part of this, dlopen_bpf_full() (which already took a log_level) is
merged into dlopen_bpf() rather than keeping both.
The static inline fallbacks used to live in the headers, which required
pulling log.h in from every header that declared a dlopen_xxx(). Move
them into the .c files instead: the declaration is always outside the
#if HAVE_XXX block, the impl sits outside the outer #if HAVE_XXX wrap
with its own internal #if HAVE_XXX/#else/#endif, and apparmor-util.c,
idn-util.c, libmount-util.c and pam-util.c are now always compiled so
they can host their stubs.
Currently, if we're copying a file, we won't copy the owner UID/GID
from the source. If we're copying a directory, we will copy the owner
UID/GID from the source. Let's give users a bit more control over this
behavior by introducing --copy-ownership= which will default to the
current behavior but allows users to explicitly enable/disable copying
of ownership.
Now that sd-event doesn't insist on blocking
SIGCHLD anymore when watching for process exit,
let's stop blocking SIGCHLD tree-wide where not
required anymore.
Alpine/postmarketOS build coreutils with --enable-single-binary=symlinks.
In that case, all commands provided by coreutils are symlink to
/usr/bin/coreutils, and it calls prctl(PR_SET_NAME, argv[0]), hence the comm
will be the path to the symlink.
This also makes not kill sleep command with SIGKILL in TEST-17-UDEV, that is
totally unnecessary.
running_in_chroot() will fail when a test is executed as a non-root
user without CAP_DAC_READ_SEARCH as it won't be able to access
/proc/1/root.
Let's make things more robust by skipping tests if we can't detect
if we're in a chroot or not, since if we can't even detect if we're
in a chroot or not, chances are we're missing the required privileges
to execute the test anyway.
sys/prctl.h anyway includes linux/prctl.h and actually these .c files
includes sys/prctl.h. Hence, it is not necessary to explicitly include
linux/prctl.h.
When we are running in chroot, safe_fork() with FORK_MOUNTNS_SLAVE fails
with the following eror:
```
Failed to set mount propagation to MS_SLAVE for all mounts: Invalid argument
```
Let's skip the test cases when we are running in chroot.
We use symbols provided by unistd.h without including it. E.g.
open(), close(), read(), write(), access(), symlink(), unlink(), rmdir(),
fsync(), syncfs(), lseek(), ftruncate(), fchown(), dup2(), pipe2(),
getuid(), getgid(), gettid(), getppid(), pipe2(), execv(), _exit(),
environ, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, F_OK, and their
friends and variants, so on.
Currently, unistd.h is indirectly included mainly in the following two paths:
- through missing_syscall.h, which is planned to covert to .c file.
- through signal.h -> bits/sigstksz.h, which is new since glibc-2.34.
Note, signal.h is included by sd-eevent.h. So, many source files
indirectly include unistd.h if newer glibc is used.
Currently, our baseline on glibc is 2.31. We need to support glibc older
than 2.34, but unfortunately, we do not have any CI environments with
such old glibc. CIFuzz uses glibc-2.31, but it builds only fuzzers, and
many files are even not compiled.
To make sure everything still compiles, we add a preliminary include
of forward.h to tests.h to make sure it is included in every test source
file. We'll clean up the tests.h includes in a later commit.
We also add a <errno.h> include to errno-list.h to keep test-errno-list.c
compiling. It'll be removed again when we clean up includes in src/basic.
Split out of #37344.
The test fails when running under sanitizers due to missing sanitizer
libraries. For now, let's skip the test until we can make the necessary
changes to run it under sanitizers.
s390x will define both s390x and s390, so exec-personality-s390.service is ran
in both cases but fails on s390x, as the personality returned is s390x.
Split the test and check specifically for s390x.
Since e56a8790a0 debugging test-execute fails has been a royal PITA, since
we ditch all potentially useful output from the test units (that, for
the most part, run `sh -x ...`). Let's improve the situation a bit by
setting EXEC_OUTPUT_NULL only when running the single test case that
needs it, and inheriting stdout otherwise.
For example, with a purposefully introduced error we get this output
with this patch:
exec-personality-x86-64.service: About to execute: sh -x -c "c=\$\$(uname -m); test \"\$\$c\" = \"foo_bar\""
Serializing sd-executor-state to memfd.
...
Personality: x86-64
LockPersonality: no
SystemCallErrorNumber: kill
++ uname -m
+ c=x86_64
+ test x86_64 = foo_bar
Received SIGCHLD from PID 1520588 (sh).
Child 1520588 (sh) died (code=exited, status=1/FAILURE)
exec-personality-x86-64.service: Child 1520588 belongs to exec-personality-x86-64.service.
exec-personality-x86-64.service: Main process exited, code=exited, status=1/FAILURE
exec-personality-x86-64.service: Failed with result 'exit-code'.
...
Exit Status: 1
src/test/test-execute.c:456:test_exec_personality: exec-personality-x86-64.service: can_unshare=yes: exit status 1, expected 0
(test-execute-root) terminated by signal ABRT.
Assertion 'r >= 0' failed at src/test/test-execute.c:1433, function prepare_ns(). Aborting.
Aborted
But without it, we'd miss the most important part:
exec-personality-x86-64.service: About to execute: sh -x -c "c=\$\$(uname -m); test \"\$\$c\" = \"foo_bar\""
Serializing sd-executor-state to memfd.
...
Personality: x86-64
LockPersonality: no
SystemCallErrorNumber: kill
Received SIGCHLD from PID 1521365 (sh).
Child 1521365 (sh) died (code=exited, status=1/FAILURE)
exec-personality-x86-64.service: Child 1521365 belongs to exec-personality-x86-64.service.
exec-personality-x86-64.service: Main process exited, code=exited, status=1/FAILURE
exec-personality-x86-64.service: Failed with result 'exit-code'.
...
Exit Status: 1
src/test/test-execute.c:456:test_exec_personality: exec-personality-x86-64.service: can_unshare=yes: exit status 1, expected 0
(test-execute-root) terminated by signal ABRT.
Assertion 'r >= 0' failed at src/test/test-execute.c:1433, function prepare_ns(). Aborting.
Aborted
If we're running test-execute from the build directory which is under
one of the tmpfs-ed directories (i.e. /root or /tmp), test-execute might
behave strangely, since in that case manager_new() pins the system
systemd-executor binary instead of the build dir one, which may lead to
a very confusing test fails (if there's enough difference between the
system and built sd-executor binary). Let's account for that and
bind-mount the build dir under the tmpfs-ed directory if necessary.
Bump the timeout for test-execute subtests if running with plain QEMU
(as part of TEST-02-UNITTESTS), since we might start hitting the default
2m timeout with some more involved subtests, especially when the AWS
region we're running in is under heavy load. I see this regularly in the
CentOS Stream 9 nightly cron job with exec-dynamicuser-statedir.service
which has a lot of ExecStart's.
Some tests in test-execute are already skipped if we do not have
unprivileged user namespaces. Extend this check to look for an apparmor
specific sysctl indicating that unprivileged userns creation is
restricted.
With newer versions of AppArmor, unprivileged user namespace creation
may be restricted by default, in which case user manager instances will
not be able to apply PrivateUsers=yes (or the settings which require it).
Additionally, if a kernel has the kernel.unprivileged_userns_clone
sysctl patch, and that sysctl is 0, then unprivileged userns creation
will always fail.
If a test unit is going to be run in a user manager, and that unit
requires PrivateUsers=yes (explicitly or implicitly), then skip it if
we do not have user namespace privileges.
In some environments, such as a LXD container, the netns setup might
fail because ip netns exec fails trying to mount /sys:
$ systemd-detect-virt
lxc
$ ip link add dummy-test-exec type dummy
$ ip netns add test-execute-netns
$ ip netns exec test-execute-netns ip link add dummy-test-ns type dummy
mount of /sys failed: Operation not permitted
If this setup fails, test_exec_networknamespacepath will fail, so check
the exit codes for these setup calls and skip the test if necessary.