1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-24 21:34:08 +03:00

test-resolved-stream: before entering user/network namespaces check if that's safe

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.
This commit is contained in:
Lennart Poettering 2022-04-01 10:56:41 +02:00
parent 8419213d99
commit ed59b44309

View File

@ -16,6 +16,7 @@
#include "fd-util.h"
#include "log.h"
#include "macro.h"
#include "path-util.h"
#include "process-util.h"
#include "resolved-dns-packet.h"
#include "resolved-dns-question.h"
@ -330,11 +331,36 @@ static void test_dns_stream(bool tls) {
static void try_isolate_network(void) {
_cleanup_close_ int socket_fd = -1;
int r;
if (unshare(CLONE_NEWUSER | CLONE_NEWNET) < 0) {
log_warning("test-resolved-stream: Can't create user and network ns, running on host");
return;
/* First test if CLONE_NEWUSER/CLONE_NEWNET can actually work for us, i.e. we can open the namespaces
* and then still access the build dir we are run from. We do that in a child process since it's
* nasty if we have to go back from the namespace once we entered it and realized it cannot work. */
r = safe_fork("(usernstest)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
if (r == 0) { /* child */
_cleanup_free_ char *rt = NULL, *d = NULL;
if (unshare(CLONE_NEWUSER | CLONE_NEWNET) < 0) {
log_warning_errno(errno, "test-resolved-stream: Can't create user and network ns, running on host: %m");
_exit(EXIT_FAILURE);
}
assert_se(get_process_exe(0, &rt) >= 0);
assert_se(path_extract_directory(rt, &d) >= 0);
if (access(d, F_OK) < 0) {
log_warning_errno(errno, "test-resolved-stream: Can't access /proc/self/exe from user/network ns, running on host: %m");
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
if (r == -EPROTO) /* EPROTO means nonzero exit code of child, i.e. the tests in the child failed */
return;
assert_se(r > 0);
/* Now that we know that the unshare() is safe, let's actually do it */
assert_se(unshare(CLONE_NEWUSER | CLONE_NEWNET) >= 0);
/* Bring up the loopback interfaceon the newly created network namespace */
struct ifreq req = { .ifr_ifindex = 1 };