As @yuwata correctly points out, this became broken when log_debug()
started returning -EIO. I wanted to preserve this pattern, but it turns
out it is not very widely used, and preserving it would make the whole
thing, already quite complicated, even more complex.
log_debug() is made like log_info() and friends, and returns void.
basic/log: assert that 0 is not passed as errno, except in test code
Let's assert if we ever happen to pass 0 to one of the log functions.
With the preceding commit to return -EIO from log_*(), passing 0 wouldn't
affect the return value any more, but it is still most likely an error.
The unit test code is an exception: we fairly often pass the return value
to print it, before checking what it is. So let's assert that we're not
passing 0 in non-test code. As with the previous check for %m, this is only
done in developer mode. We are depending on external code setting
errno correctly for us, which might not always be true, and which we can't
test, so we shouldn't assert, but just handle this gracefully.
I did a bunch of greps to try to figure out if there are any places where
we're passing 0 on purpose, and couldn't find any.
The one place that failed in tests is adjusted.
About "zerook" in the name: I wanted the suffix to be unambiguous. It's a
single "word" because each of the words in log_full_errno is also meaningful,
and having one term use two words would be confusing.
basic/log: assert that %m is not used when error is not set
This is only done in developer mode. It is a pretty rare occurence that we
make this kind of mistake. And even if it happens, the result is just a misleading
error message. So let's only do the check in non-release builds.
This silences some warnigns where gcc thinks that some variables are
unitialized. One particular case:
../src/journal/journald-server.c: In function 'ache_space_refresh':
../src/journal/journald-server.c:136:28: error: 'vfs_avail' may be used uninitialized in this function [-Werror=maybe-uninitialized]
136 | uint64_t vfs_used, vfs_avail, avail;
| ^~~~~~~~~
../src/journal/journald-server.c:136:18: error: 'vfs_used' may be used uninitialized in this function [-Werror=maybe-uninitialized]
136 | uint64_t vfs_used, vfs_avail, avail;
| ^~~~~~~~
cc1: all warnings being treated as errors
which is caused by
d = opendir(path);
if (!d)
return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR,
errno, "Failed to open %s: %m", path);
if (fstatvfs(dirfd(d), &ss) < 0)
return log_error_errno(errno, "Failed to fstatvfs(%s): %m", path);
For some reason on aarch64 gcc thinks we might return non-negative here. In
principle errno must be set in both cases, but it's hard to say for certain.
So let's make sure that our code flow is correct, even if somebody forgot to
set the global variable somewhere.
Using a enum is all nice and generic, but at this point it seems unlikely that
we'll add further build modes. But having an enum means that we need to include
the header file with the enumeration whenerever the conditional is used. I want
to use the conditional in log.h, which makes it hard to avoid circular imports.
tree-wide: avoid uninitialized warning on _cleanup_ variables
With some versions of the compiler, the _cleanup_ attr makes it think
the variable might be freed/closed when uninitialized, even though it
cannot happen. The added cost is small enough to be worth the benefit,
and optimized builds will help reduce it even further.
meson: build tests with -Wno-maybe-uninitialized if -O2/-flto are used
We intentionally do not inline initializations with definitions for
a bunch of _cleanup_ variables in tests, to ensure valgrind is triggered.
This triggers a lot of maybe-uninitialized false positives when -O2 and
-flto are used. Suppress them.
packit: drop the 'sources' file after cloning the Fedora repo
Otherwise rebase-helper thinks we're are a dist-git repository,
replacing the generated git archive with PR changes with the tarball
found in the 'sources' file.
There are two ambiguity in the original description:
1. It will delay all RUN instructions, include builtin.
2. It will delay before running RUN, not each of RUN{program} instructions.
The test occasionally fails as the umount is not yet completed when
cryptsetup close is invoked.
Both cryptsetup and losetup have supported deferred cleanup for some
time now, so use it instead to avoid races.
++ losetup -P --show --find /tmp/test-repart.dMOfYQ8UUF/zzz
+ LOOP=/dev/loop6
+ VOLUME=test-repart-11882
+ touch /tmp/test-repart.dMOfYQ8UUF/empty-password
+ cryptsetup open --type=luks2 --key-file=/tmp/test-repart.dMOfYQ8UUF/empty*** test-repart-11882
+ mkdir /tmp/test-repart.dMOfYQ8UUF/mount
+ mount -t ext4 /dev/mapper/test-repart-11882 /tmp/test-repart.dMOfYQ8UUF/mount
+ diff -r /tmp/test-repart.dMOfYQ8UUF/mount/def /tmp/test-repart.dMOfYQ8UUF/definitions
+ umount /tmp/test-repart.dMOfYQ8UUF/mount
+ cryptsetup close test-repart-11882
Device test-repart-11882 is still in use.
+ rm -rf /tmp/test-repart.dMOfYQ8UUF
Julia Kartseva [Wed, 9 Dec 2020 06:07:30 +0000 (22:07 -0800)]
dbus-cgroup: add BPFProgram= dbus support
- Handle BPFProgram= property in string format
"<bpf_attach_type>:<bpffs_path>", e.g. egress:/sys/fs/bpf/egress-hook.
- Add dbus getter to list foreign bpf programs attached to a cgroup.
Julia Kartseva [Wed, 4 Sep 2019 02:08:13 +0000 (19:08 -0700)]
tests: add unit file tests for BPFProgram=
- Pin trivial bpf programs to bpf filesystem, compose BPFProgram= option
string and pass it to a unit. Programs store `0` in r0 BPF register for
denying action, e.g. drop a packet.
- Load trivial BPF programs
- Test is skipped if not run under root or if can not lock enough
memory.
- For egress and ingress hooks, test BPFProgram= option along with
with IP{Egress|Ingress}FilterPath=, expected result should not depend on
which rule is executed first.
Expected results for BPF_CGROUP_INET_INGRESS:
5 packets transmitted, 0 received, 100% packet loss, time 89ms
For BPF_CGROUP_INET_SOCK_CREATE:
ping: socket: Operation not permitted
Julia Kartseva [Wed, 16 Sep 2020 22:58:04 +0000 (15:58 -0700)]
core: add bpf-foreign unit helpers
- Introduce support of cgroup-bpf programs managed (i.e. compiled,
loaded to and unloaded from kernel) externally. Systemd is only
responsible for attaching programs to unit cgroup hence the name
'foreign'.
Foreign BPF programs are identified by bpf program ID and attach type.
systemd:
- Gets kernel FD of BPF program;
- Makes a unique identifier of BPF program from BPF attach type and
program ID. Same program IDs mean the same program, i.e the same
chunk of kernel memory. Even if the same program is passed multiple
times, identical (program_id, attach_type) instances are collapsed
into one;
- Attaches programs to unit cgroup.
Julia Kartseva [Tue, 2 Mar 2021 00:56:04 +0000 (16:56 -0800)]
cgroup: add foreign program to cgroup context
- Store foreign bpf programs in cgroup context. A program is considered
foreign if it was loaded to a kernel by an entity external to systemd,
so systemd is responsible only for attach and detach paths.
- Support the case of pinned bpf programs: pinning to bpffs so a program
is kept loaded to the kernel even when program fd is closed by a user
application is a common way to extend program's lifetime.
- Aadd linked list node struct with attach type and bpffs path
fields.
Julia Kartseva [Thu, 4 Feb 2021 08:02:07 +0000 (00:02 -0800)]
shared: bpf_attach_type {from,to} string
Introduce bpf_cgroup_attach_type_table with accustomed attached type
names also used in bpftool.
Add bpf_cgroup_attach_type_{from|to}_string helpers to convert from|to
string representation of pinned bpf program, e.g.
"egress:/sys/fs/bpf/egress-hook" for
/sys/fs/bpf/egress-hook path and BPF_CGROUP_INET_EGRESS attach type.
Julia Kartseva [Wed, 16 Sep 2020 22:58:04 +0000 (15:58 -0700)]
shared: add bpf-program helpers
Add helpers to:
- Create new BPFProgram instance from a path in bpf
filesystem and bpf attach type;
- Pin a program to bpf fs;
- Get BPF program ID by BPF program FD.
We were grepping for 'hello world', and in the namespace we would
match on 'hello world', and outside, on 'echo "hello world"'. When
the condition check was fixed, the test gave a false positive.
We were invoking 'systemd-run bash', but the test invoked by bash
was not effective. When the result of that check is propagated, the
outer command fails.
tmpfiles: make handling of existing-but-different targets more consistent
create_fifo() was added in a2fc2f8dd30c17ad1e23a31fc6ff2aeba4c6fa27, and
would always ignore failure. The test was trying to fail in this case, but
we actually don't fail, which seems to be correct. We didn't notice before
because the test was ineffective.
To make things consistent, generally log at warning level, but don't propagate
the error. For symlinks, log at debug level, as before.
For 'e', failure is not propagated now. The test is adjusted to match.
I think warning is appropriate in most cases: we do not expect a device node to
be replaced by a different device node or even a non-device file. This would
most likely be an error somewhere. An exception is made for symlinks, which are
mismatched on purpose, for example /etc/resolv.conf. With this patch, we don't
get any warnings with the any of the 74 tmpfiles.d files, which suggests that
increasing the warning levels will not cause too many unexpected warnings. If
it turns out that there are valid cases where people have expected mismatches
for non-symlink types, we can always decrease the log levels again.
Also add "system" in the messages, because we set the internal value,
and are just skipping the setting of the external value, so the message
could be confusing without that clarification.
We didn't document this behaviour one way or another, so I think it's
OK to change. All callers do the NULL check before callling this to avoid
the assert warning, so it seems reasonable to do it internally.
sd_bus_can_send() is similar, but there we expressly say that an
error is returned on NULL, so I didn't change it.
scsi_id: modernize and use extract_many_words instead of strsep
Also use standard error loggin/return pattern.
Only cursory tested, by checking that with a simple config file
the array is the same before/after. Not tested with actual scsi
rules and devices, due to missing hardware.
Some static analyzers (lgtm) warn against using non-re-entrant functions,
even though at the moment this code is not multi-threaded, just switch to
format_timestamp.
After #19168, #19169, and #19175, there are no warnings with
-Dbuildtype=debug-optimized/-O2 and gcc-11.0.1-0.3.fc34.x86_64. Warnings
are reenabled for -O[23]
-O0 is good for development, and -O2 is the default optimization level for
Fedora package builds. -Os, -O3, -O1, and -Og still generate some warnings. In
fact, with -Os the number of warnings seems completely hopeless. Dozens and
dozens.
home: use goto to make it clear that variables are initialized
gcc-11.0.1-0.3.fc34.x86_64 with -Og was complaining that 'r' might be
unitialized. It cannot, but let's rework the code to use a goto instead of
conditionalizing on 'call' being unset, which I think is clearer and less error
prone. This silences the warning.