Skip to content

Commit ca782b8

Browse files
authored
Merge pull request systemd#22934 from poettering/tls-test-fix-root
tests: make test-resolved-stream suceed even when run as root with restrictive access mode on build tree dir
2 parents aed3c5e + ed59b44 commit ca782b8

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
lines changed

src/resolve/test-resolved-stream.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "fd-util.h"
1717
#include "log.h"
1818
#include "macro.h"
19+
#include "path-util.h"
1920
#include "process-util.h"
2021
#include "resolved-dns-packet.h"
2122
#include "resolved-dns-question.h"
@@ -330,11 +331,36 @@ static void test_dns_stream(bool tls) {
330331

331332
static void try_isolate_network(void) {
332333
_cleanup_close_ int socket_fd = -1;
334+
int r;
333335

334-
if (unshare(CLONE_NEWUSER | CLONE_NEWNET) < 0) {
335-
log_warning("test-resolved-stream: Can't create user and network ns, running on host");
336-
return;
336+
/* First test if CLONE_NEWUSER/CLONE_NEWNET can actually work for us, i.e. we can open the namespaces
337+
* and then still access the build dir we are run from. We do that in a child process since it's
338+
* nasty if we have to go back from the namespace once we entered it and realized it cannot work. */
339+
r = safe_fork("(usernstest)", FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
340+
if (r == 0) { /* child */
341+
_cleanup_free_ char *rt = NULL, *d = NULL;
342+
343+
if (unshare(CLONE_NEWUSER | CLONE_NEWNET) < 0) {
344+
log_warning_errno(errno, "test-resolved-stream: Can't create user and network ns, running on host: %m");
345+
_exit(EXIT_FAILURE);
346+
}
347+
348+
assert_se(get_process_exe(0, &rt) >= 0);
349+
assert_se(path_extract_directory(rt, &d) >= 0);
350+
351+
if (access(d, F_OK) < 0) {
352+
log_warning_errno(errno, "test-resolved-stream: Can't access /proc/self/exe from user/network ns, running on host: %m");
353+
_exit(EXIT_FAILURE);
354+
}
355+
356+
_exit(EXIT_SUCCESS);
337357
}
358+
if (r == -EPROTO) /* EPROTO means nonzero exit code of child, i.e. the tests in the child failed */
359+
return;
360+
assert_se(r > 0);
361+
362+
/* Now that we know that the unshare() is safe, let's actually do it */
363+
assert_se(unshare(CLONE_NEWUSER | CLONE_NEWNET) >= 0);
338364

339365
/* Bring up the loopback interfaceon the newly created network namespace */
340366
struct ifreq req = { .ifr_ifindex = 1 };

src/shared/tests.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,23 +48,26 @@ char* setup_fake_runtime_dir(void) {
4848

4949
static void load_testdata_env(void) {
5050
static bool called = false;
51-
_cleanup_free_ char *s = NULL;
52-
_cleanup_free_ char *envpath = NULL;
51+
_cleanup_free_ char *s = NULL, *d = NULL, *envpath = NULL;
5352
_cleanup_strv_free_ char **pairs = NULL;
53+
int r;
5454

5555
if (called)
5656
return;
5757
called = true;
5858

5959
assert_se(readlink_and_make_absolute("/proc/self/exe", &s) >= 0);
60-
dirname(s);
60+
assert_se(path_extract_directory(s, &d) >= 0);
61+
assert_se(envpath = path_join(d, "systemd-runtest.env"));
6162

62-
envpath = path_join(s, "systemd-runtest.env");
63-
if (load_env_file_pairs(NULL, envpath, &pairs) < 0)
63+
r = load_env_file_pairs(NULL, envpath, &pairs);
64+
if (r < 0) {
65+
log_debug_errno(r, "Reading %s failed: %m", envpath);
6466
return;
67+
}
6568

6669
STRV_FOREACH_PAIR(k, v, pairs)
67-
setenv(*k, *v, 0);
70+
assert_se(setenv(*k, *v, 0) >= 0);
6871
}
6972

7073
int get_testdata_dir(const char *suffix, char **ret) {

0 commit comments

Comments
 (0)