1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include <sys/socket.h>
13 #include "alloc-util.h"
16 #include "namespace-util.h"
17 #include "namespace.h"
19 #include "process-util.h"
20 #include "string-util.h"
22 #include "uid-range.h"
23 #include "user-util.h"
26 TEST(namespace_cleanup_tmpdir
) {
28 _cleanup_(namespace_cleanup_tmpdirp
) char *dir
;
29 assert_se(dir
= strdup(RUN_SYSTEMD_EMPTY
));
33 _cleanup_(namespace_cleanup_tmpdirp
) char *dir
;
34 assert_se(dir
= strdup("/tmp/systemd-test-namespace.XXXXXX"));
35 assert_se(mkdtemp(dir
));
39 static void test_tmpdir_one(const char *id
, const char *A
, const char *B
) {
40 _cleanup_free_
char *a
, *b
;
44 assert_se(setup_tmp_dirs(id
, &a
, &b
) == 0);
46 assert_se(stat(a
, &x
) >= 0);
47 assert_se(stat(b
, &y
) >= 0);
49 assert_se(S_ISDIR(x
.st_mode
));
50 assert_se(S_ISDIR(y
.st_mode
));
52 if (!streq(a
, RUN_SYSTEMD_EMPTY
)) {
53 assert_se(startswith(a
, A
));
54 assert_se((x
.st_mode
& 01777) == 0700);
55 c
= strjoina(a
, "/tmp");
56 assert_se(stat(c
, &x
) >= 0);
57 assert_se(S_ISDIR(x
.st_mode
));
58 assert_se(FLAGS_SET(x
.st_mode
, 01777));
59 assert_se(rmdir(c
) >= 0);
60 assert_se(rmdir(a
) >= 0);
63 if (!streq(b
, RUN_SYSTEMD_EMPTY
)) {
64 assert_se(startswith(b
, B
));
65 assert_se((y
.st_mode
& 01777) == 0700);
66 d
= strjoina(b
, "/tmp");
67 assert_se(stat(d
, &y
) >= 0);
68 assert_se(S_ISDIR(y
.st_mode
));
69 assert_se(FLAGS_SET(y
.st_mode
, 01777));
70 assert_se(rmdir(d
) >= 0);
71 assert_se(rmdir(b
) >= 0);
76 _cleanup_free_
char *x
= NULL
, *y
= NULL
, *z
= NULL
, *zz
= NULL
;
79 assert_se(sd_id128_get_boot(&bid
) >= 0);
81 x
= strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid
), "-abcd.service-");
82 y
= strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid
), "-abcd.service-");
85 test_tmpdir_one("abcd.service", x
, y
);
87 z
= strjoin("/tmp/systemd-private-", SD_ID128_TO_STRING(bid
), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-");
88 zz
= strjoin("/var/tmp/systemd-private-", SD_ID128_TO_STRING(bid
), "-sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device-");
92 test_tmpdir_one("sys-devices-pci0000:00-0000:00:1a.0-usb3-3\\x2d1-3\\x2d1:1.0-bluetooth-hci0.device", z
, zz
);
95 static void test_shareable_ns(unsigned long nsflag
) {
96 _cleanup_close_pair_
int s
[2] = EBADF_PAIR
;
97 bool permission_denied
= false;
98 pid_t pid1
, pid2
, pid3
;
103 (void) log_tests_skipped("not root");
107 assert_se(socketpair(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0, s
) >= 0);
110 assert_se(pid1
>= 0);
113 r
= setup_shareable_ns(s
, nsflag
);
114 assert_se(r
>= 0 || ERRNO_IS_NEG_PRIVILEGE(r
));
115 _exit(r
>= 0 ? r
: EX_NOPERM
);
119 assert_se(pid2
>= 0);
122 r
= setup_shareable_ns(s
, nsflag
);
123 assert_se(r
>= 0 || ERRNO_IS_NEG_PRIVILEGE(r
));
124 _exit(r
>= 0 ? r
: EX_NOPERM
);
128 assert_se(pid3
>= 0);
131 r
= setup_shareable_ns(s
, nsflag
);
132 assert_se(r
>= 0 || ERRNO_IS_NEG_PRIVILEGE(r
));
133 _exit(r
>= 0 ? r
: EX_NOPERM
);
136 r
= wait_for_terminate(pid1
, &si
);
138 assert_se(si
.si_code
== CLD_EXITED
);
139 if (si
.si_status
== EX_NOPERM
)
140 permission_denied
= true;
144 r
= wait_for_terminate(pid2
, &si
);
146 assert_se(si
.si_code
== CLD_EXITED
);
147 if (si
.si_status
== EX_NOPERM
)
148 permission_denied
= true;
152 r
= wait_for_terminate(pid3
, &si
);
154 assert_se(si
.si_code
== CLD_EXITED
);
155 if (si
.si_status
== EX_NOPERM
)
156 permission_denied
= true;
160 /* LSMs can cause setup_shareable_ns() to fail with permission denied, do not fail the test in that
161 * case (e.g.: LXC with AppArmor on kernel < v6.2). */
162 if (permission_denied
)
163 return (void) log_tests_skipped("insufficient privileges");
169 test_shareable_ns(CLONE_NEWNET
);
173 test_shareable_ns(CLONE_NEWIPC
);
176 TEST(fd_is_namespace
) {
177 _cleanup_close_
int fd
= -EBADF
;
179 ASSERT_OK_ZERO(fd_is_namespace(STDIN_FILENO
, NAMESPACE_NET
));
180 ASSERT_OK_ZERO(fd_is_namespace(STDOUT_FILENO
, NAMESPACE_NET
));
181 ASSERT_OK_ZERO(fd_is_namespace(STDERR_FILENO
, NAMESPACE_NET
));
183 fd
= namespace_open_by_type(NAMESPACE_MOUNT
);
184 if (IN_SET(fd
, -ENOSYS
, -ENOPKG
)) {
185 log_notice("Path %s not found, skipping test", "/proc/self/ns/mnt");
189 ASSERT_OK_POSITIVE(fd_is_namespace(fd
, NAMESPACE_MOUNT
));
190 ASSERT_OK_ZERO(fd_is_namespace(fd
, NAMESPACE_NET
));
193 ASSERT_OK(fd
= namespace_open_by_type(NAMESPACE_IPC
));
194 ASSERT_OK_POSITIVE(fd_is_namespace(fd
, NAMESPACE_IPC
));
197 ASSERT_OK(fd
= namespace_open_by_type(NAMESPACE_NET
));
198 ASSERT_OK_POSITIVE(fd_is_namespace(fd
, NAMESPACE_NET
));
201 TEST(protect_kernel_logs
) {
202 static const NamespaceParameters p
= {
203 .runtime_scope
= RUNTIME_SCOPE_SYSTEM
,
204 .protect_kernel_logs
= true,
210 (void) log_tests_skipped("not root");
214 /* In a container we likely don't have access to /dev/kmsg */
215 if (detect_container() > 0) {
216 (void) log_tests_skipped("in container");
224 _cleanup_close_
int fd
= -EBADF
;
226 fd
= open("/dev/kmsg", O_RDONLY
| O_CLOEXEC
);
229 r
= setup_namespace(&p
, NULL
);
232 assert_se(setresuid(UID_NOBODY
, UID_NOBODY
, UID_NOBODY
) >= 0);
233 assert_se(open("/dev/kmsg", O_RDONLY
| O_CLOEXEC
) < 0);
234 assert_se(errno
== EACCES
);
239 assert_se(wait_for_terminate_and_check("ns-kernellogs", pid
, WAIT_LOG
) == EXIT_SUCCESS
);
242 TEST(idmapping_supported
) {
243 assert_se(is_idmapping_supported("/run") >= 0);
244 assert_se(is_idmapping_supported("/var/lib") >= 0);
245 assert_se(is_idmapping_supported("/var/cache") >= 0);
246 assert_se(is_idmapping_supported("/var/log") >= 0);
247 assert_se(is_idmapping_supported("/etc") >= 0);
250 TEST(namespace_is_init
) {
253 for (NamespaceType t
= 0; t
< _NAMESPACE_TYPE_MAX
; t
++) {
254 r
= namespace_is_init(t
);
256 log_info_errno(r
, "In root namespace of type '%s': don't know", namespace_info
[t
].proc_name
);
259 log_info("In root namespace of type '%s': %s", namespace_info
[t
].proc_name
, yes_no(r
));
264 TEST(userns_get_base_uid
) {
265 _cleanup_close_
int fd
= -EBADF
;
267 fd
= userns_acquire("0 1 1", "0 2 1", /* setgroups_deny= */ true);
268 if (ERRNO_IS_NEG_NOT_SUPPORTED(fd
))
269 return (void) log_tests_skipped("userns is not supported");
270 if (ERRNO_IS_NEG_PRIVILEGE(fd
))
271 return (void) log_tests_skipped("lacking userns privileges");
273 uid_t base_uid
, base_gid
;
274 ASSERT_OK(userns_get_base_uid(fd
, &base_uid
, &base_gid
));
275 ASSERT_EQ(base_uid
, 1U);
276 ASSERT_EQ(base_gid
, 2U);
278 ASSERT_ERROR(userns_get_base_uid(fd
, &base_uid
, NULL
), EUCLEAN
);
282 fd
= userns_acquire_empty();
285 ASSERT_ERROR(userns_get_base_uid(fd
, &base_uid
, &base_gid
), ENOMSG
);
288 TEST(process_is_owned_by_uid
) {
291 /* Test our own PID */
292 _cleanup_(pidref_done
) PidRef pid
= PIDREF_NULL
;
293 ASSERT_OK(pidref_set_self(&pid
));
294 ASSERT_OK_POSITIVE(process_is_owned_by_uid(&pid
, getuid()));
298 return (void) log_tests_skipped("lacking userns privileges");
300 _cleanup_(uid_range_freep
) UIDRange
*range
= NULL
;
301 ASSERT_OK(uid_range_load_userns(/* path= */ NULL
, UID_RANGE_USERNS_INSIDE
, &range
));
302 if (!uid_range_contains(range
, 1))
303 return (void) log_tests_skipped("UID 1 not included in userns UID delegation, skipping test");
305 /* Test a child that runs as uid 1 */
306 _cleanup_close_pair_
int p
[2] = EBADF_PAIR
;
307 ASSERT_OK_ERRNO(pipe2(p
, O_CLOEXEC
));
309 r
= pidref_safe_fork("(child)", FORK_RESET_SIGNALS
|FORK_DEATHSIG_SIGKILL
, &pid
);
312 p
[0] = safe_close(p
[0]);
313 ASSERT_OK(fully_set_uid_gid(1, 1, NULL
, 0));
314 ASSERT_OK_EQ_ERRNO(write(p
[1], &(const char[]) { 'x' }, 1), 1);
315 p
[1] = safe_close(p
[1]);
319 p
[1] = safe_close(p
[1]);
321 ASSERT_OK_EQ_ERRNO(read(p
[0], &x
, 1), 1);
323 p
[0] = safe_close(p
[0]);
325 ASSERT_OK_ZERO(process_is_owned_by_uid(&pid
, getuid()));
327 ASSERT_OK(pidref_kill(&pid
, SIGKILL
));
328 ASSERT_OK(pidref_wait_for_terminate(&pid
, /* ret= */ NULL
));
330 /* Test a child that runs in a userns as uid 1, but the userns is owned by us */
331 ASSERT_OK_ERRNO(pipe2(p
, O_CLOEXEC
));
333 _cleanup_close_pair_
int pp
[2] = EBADF_PAIR
;
334 ASSERT_OK_ERRNO(pipe2(pp
, O_CLOEXEC
));
336 r
= pidref_safe_fork("(child)", FORK_RESET_SIGNALS
|FORK_DEATHSIG_SIGKILL
|FORK_NEW_USERNS
, &pid
);
339 p
[0] = safe_close(p
[0]);
340 pp
[1] = safe_close(pp
[1]);
343 ASSERT_OK_EQ_ERRNO(read(pp
[0], &x
, 1), 1);
345 pp
[0] = safe_close(pp
[0]);
347 ASSERT_OK(reset_uid_gid());
349 ASSERT_OK_EQ_ERRNO(write(p
[1], &(const char[]) { 'x' }, 1), 1);
350 p
[1] = safe_close(p
[1]);
354 p
[1] = safe_close(p
[1]);
355 pp
[0] = safe_close(pp
[0]);
357 ASSERT_OK(write_string_file(procfs_file_alloca(pid
.pid
, "uid_map"), "0 1 1\n", 0));
358 ASSERT_OK(write_string_file(procfs_file_alloca(pid
.pid
, "setgroups"), "deny", 0));
359 ASSERT_OK(write_string_file(procfs_file_alloca(pid
.pid
, "gid_map"), "0 1 1\n", 0));
361 ASSERT_OK_EQ_ERRNO(write(pp
[1], &(const char[]) { 'x' }, 1), 1);
362 pp
[1] = safe_close(pp
[1]);
365 ASSERT_OK_EQ_ERRNO(read(p
[0], &x
, 1), 1);
367 p
[0] = safe_close(p
[0]);
369 ASSERT_OK_POSITIVE(process_is_owned_by_uid(&pid
, getuid()));
371 ASSERT_OK(pidref_kill(&pid
, SIGKILL
));
372 ASSERT_OK(pidref_wait_for_terminate(&pid
, /* ret= */ NULL
));
375 TEST(namespace_get_leader
) {
378 _cleanup_(pidref_done
) PidRef original
= PIDREF_NULL
;
379 ASSERT_OK(pidref_set_self(&original
));
381 _cleanup_(pidref_done
) PidRef pid
= PIDREF_NULL
;
382 r
= pidref_safe_fork("(child)", FORK_RESET_SIGNALS
|FORK_DEATHSIG_SIGKILL
|FORK_NEW_MOUNTNS
|FORK_WAIT
|FORK_LOG
, &pid
);
386 _cleanup_(pidref_done
) PidRef pid2
= PIDREF_NULL
;
387 r
= pidref_safe_fork("(child)", FORK_RESET_SIGNALS
|FORK_DEATHSIG_SIGKILL
|FORK_WAIT
|FORK_LOG
, &pid2
);
391 log_info("PID hierarchy: " PID_FMT
" ← " PID_FMT
" ← " PID_FMT
, original
.pid
, pid
.pid
, pid2
.pid
);
393 _cleanup_(pidref_done
) PidRef self
= PIDREF_NULL
;
394 ASSERT_OK(pidref_set_self(&self
));
395 ASSERT_TRUE(pidref_equal(&self
, &pid2
));
397 _cleanup_(pidref_done
) PidRef parent
= PIDREF_NULL
;
398 ASSERT_OK(pidref_set_parent(&parent
));
399 ASSERT_TRUE(pidref_equal(&parent
, &pid
));
400 ASSERT_TRUE(!pidref_equal(&self
, &pid
));
401 ASSERT_TRUE(!pidref_equal(&self
, &parent
));
403 _cleanup_(pidref_done
) PidRef grandparent
= PIDREF_NULL
;
404 ASSERT_OK(pidref_get_ppid_as_pidref(&parent
, &grandparent
));
405 ASSERT_TRUE(pidref_equal(&grandparent
, &original
));
406 ASSERT_TRUE(!pidref_equal(&grandparent
, &self
));
407 ASSERT_TRUE(!pidref_equal(&grandparent
, &pid
));
408 ASSERT_TRUE(!pidref_equal(&grandparent
, &pid2
));
409 ASSERT_TRUE(!pidref_equal(&grandparent
, &parent
));
411 _cleanup_(pidref_done
) PidRef leader
= PIDREF_NULL
;
412 ASSERT_OK(namespace_get_leader(&self
, NAMESPACE_MOUNT
, &leader
));
413 ASSERT_TRUE(pidref_equal(&parent
, &leader
));
414 ASSERT_TRUE(pidref_equal(&pid
, &leader
));
415 ASSERT_TRUE(!pidref_equal(&self
, &leader
));
416 ASSERT_TRUE(!pidref_equal(&pid2
, &leader
));
417 ASSERT_TRUE(!pidref_equal(&original
, &leader
));
418 ASSERT_TRUE(!pidref_equal(&grandparent
, &leader
));
423 TEST(detach_mount_namespace_harder
) {
424 _cleanup_(pidref_done
) PidRef pid
= PIDREF_NULL
;
425 _cleanup_close_pair_
int p
[2] = EBADF_PAIR
;
429 ASSERT_OK_ERRNO(pipe2(p
, O_CLOEXEC
));
431 ASSERT_OK(r
= pidref_safe_fork("(child)", FORK_RESET_SIGNALS
|FORK_DEATHSIG_SIGKILL
|FORK_LOG
, &pid
));
433 p
[0] = safe_close(p
[0]);
435 ASSERT_OK(detach_mount_namespace_harder(0, 0));
437 ASSERT_OK_EQ_ERRNO(write(p
[1], &(const char[]) { 'x' }, 1), 1);
441 p
[1] = safe_close(p
[1]);
442 ASSERT_OK_EQ_ERRNO(read(p
[0], &x
, 1), 1);
445 ASSERT_OK_POSITIVE(pidref_in_same_namespace(NULL
, &pid
, NAMESPACE_USER
));
446 ASSERT_OK_ZERO(pidref_in_same_namespace(NULL
, &pid
, NAMESPACE_MOUNT
));
449 static int intro(void) {
450 if (!have_namespaces())
451 return log_tests_skipped("Don't have namespace support or lacking privileges");
456 DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO
, intro
);