On Noble setting this ioctl fails:
1570s 819/1330 systemd:resolve / test-resolved-stream FAIL 0.14s killed by signal 6 SIGABRT
1570s Successfully forked off '(usernstest)' as PID 27737.
1570s Skipping PR_SET_MM, as we don't have privileges.
1570s (usernstest) succeeded.
1570s Assertion 'ioctl(socket_fd, SIOCSIFFLAGS, &req) >= 0' failed at src/resolve/test-resolved-stream.c:372, function try_isolate_network(). Aborting.
Ignore the result.
Sometimes it makes sense to hard kill a client if we die. Let's hence
add a third FORK_DEATHSIG flag for this purpose: FORK_DEATHSIG_SIGKILL.
To make things less confusing this also renames FORK_DEATHSIG to
FORK_DEATHSIG_SIGTERM to make clear it sends SIGTERM. We already had
FORK_DEATHSIG_SIGINT, hence this makes things nicely symmetric.
A bunch of users are switched over for FORK_DEATHSIG_SIGKILL where we
know it's safe to abort things abruptly. This should make some kernel
cases more robust, since we cannot get confused by signal masks or such.
While we are at it, also fix a bunch of bugs where we didn't take
FORK_DEATHSIG_SIGINT into account in safe_fork()
We use usec_t for storing time value, which is 64bit.
However, usleep() takes useconds_t that is (typically?) 32bit.
Also, usleep() may only support the range [0, 1000000].
This introduce usleep_safe() which takes usec_t.
-1 was used everywhere, but -EBADF or -EBADFD started being used in various
places. Let's make things consistent in the new style.
Note that there are two candidates:
EBADF 9 Bad file descriptor
EBADFD 77 File descriptor in bad state
Since we're initializating the fd, we're just assigning a value that means
"no fd yet", so it's just a bad file descriptor, and the first errno fits
better. If instead we had a valid file descriptor that became invalid because
of some operation or state change, the other errno would fit better.
In some places, initialization is dropped if unnecessary.
Since we don't need the error value, and the buffer is allocated with a fixed
size, the whole logic provided by in_addr_to_string() becomes unnecessary, so
it's enough to wrap inet_ntop() directly.
inet_ntop() can only fail with ENOSPC. But we specify a buffer that is supposed
to be large enough, so this should never fail. A bunch of tests of this are added.
This allows all the wrappers like strna(), strnull(), strempty() to be dropped.
The guard of 'if (DEBUG_LOGGING)' can be dropped from around log_debug(),
because log_debug() implements the check outside of the function call. But
log_link_debug() does not, so it we need it to avoid unnecessary evaluation of
the formatting.
I regularly run my tests also as root, since some of the tested code
uses privileged APIs. The test-resolved-stream so far tried to run its
tests in a user/network namespace if that can be allocated. This caused
the tests to fail on my system where once the user namespace is opened
access to the build tree in my $HOME is prohibited (due to restricted
access modes on my home dir). Let's add a check for that: before
actually isolating the test in a user/network namespace, let's see if
that would make it impossible for us to access the build tree (which we
need to do load the TLS certificates the test requires).
This should make the test pass when run as root from a build tree with
restrictive access mode.
Since test-resolved-stream brings up a simple DNS server on 127.0.0.1:12345,
only one instance could run at a time, so it would fail when run like
`meson test -C build test-resolved-stream --repeat=1000`.
Similarly, if by chance something is up on port 12345, the test would fail.
To make the test more reliable, run it in an isolated user + network namespace.
If this fails (some distributions disable user namespaces), just run as before.
In commit 2aaf6bb6e9, an issue was fixed where
systemd-resolved could get stuck for multiple seconds waiting for incoming data,
since GnuTLS/OpenSSL can buffer a TLS record, so data could be available, but
no EPOLLIN event would be generated.
To fix this, a somewhat elaborate logic consisting on asking the TLS library
whether it had buffered data, then "faking" an EPOLLIN event was implemented.
However, there is a much simpler solution: Always read as much data as available
(i.e. until we get an event like EAGAIN when trying to read) from the stream
when we get an EPOLLIN event, instead of at most a single packet per event.
This approach does not require asking the TLS library whether it has buffered
data, and the logic is exactly the same for both the TCP and TLS case.
test-resolved-stream is fixed to avoid a latent double free bug.
Tests DnsStream event handling, both for plain TCP DNS and DNS over TLS.
The DoT test requires the "openssl s_server" command line tool to mock a simple
TLS server. Thus the test's TLS part is skipped if openssl it not available.
The test works for both DNS_OVER_TLS_USE_GNUTLS and DNS_OVER_TLS_USE_OPENSSL.
The DoT case fails due to a bug, which is fixed on the next commit.