11static int privileged_failures(
void) {
12 int failed = 0, saved = -1, regular = -1;
14 CHECK(ns_set(
"admission",
"admission-domain") == 0);
15 saved = open(
"/proc/thread-self/ns/uts", O_RDONLY | O_CLOEXEC);
16 CHECK(saved >= 0 && ns_fd_identity(saved, &original) == 0);
17 regular = memfd_create(
"namespace-admission", MFD_CLOEXEC);
20 CHECK(unshare(1) == -1 && errno == EINVAL);
22 CHECK(unshare(CLONE_NEWNS) == -1 && errno == EOPNOTSUPP);
24 CHECK(unshare(CLONE_NEWUTS | CLONE_NEWNS) == -1 && errno == EOPNOTSUPP);
26 CHECK(setns(-1, CLONE_NEWUTS) == -1 && errno == EBADF);
28 CHECK(setns(regular, 0) == -1 && errno == EINVAL);
30 CHECK(setns(saved, CLONE_NEWNS) == -1 && errno == EINVAL);
32 CHECK(setns(saved, CLONE_NEWUTS | CLONE_NEWNS) == -1 && errno == EINVAL);
34 CHECK(setns(saved, 1) == -1 && errno == EINVAL);
35 CHECK(ns_path_identity(
"/proc/thread-self/ns/uts", ¤t) == 0 && ns_same(original, current));
36 CHECK(ns_expect(
"admission",
"admission-domain") == 0);
37 CHECK(setns(saved, 0) == 0 && setns(saved, CLONE_NEWUTS) == 0);
39 CHECK(read(saved, &
byte, 1) == -1);
40 CHECK(write(saved, &
byte, 1) == -1);
41 void* invalid = mmap(NULL, ns_page, PROT_READ, MAP_SHARED, saved, 0);
42 if (invalid != MAP_FAILED)
43 munmap(invalid, ns_page);
44 CHECK(invalid == MAP_FAILED);
45 CHECK(ns_expect(
"admission",
"admission-domain") == 0);
54static int unprivileged(
int command,
int report,
void* argument) {
57 int failed = 0, saved = *(
int*)argument;
59 CHECK(ns_fd_identity(saved, &before) == 0);
60 CHECK(setresuid(0, 1001, 0) == 0);
62 CHECK(geteuid() == 1001 && setfsuid((uid_t)-1) == 0);
63 CHECK(unshare(0) == 0);
65 CHECK(unshare(CLONE_NEWUTS) == -1 && errno == EPERM);
67 CHECK(setns(saved, 0) == -1 && errno == EPERM);
69 CHECK(sethostname(
"denied", 6) == -1 && errno == EPERM);
71 CHECK(setdomainname(
"denied", 6) == -1 && errno == EPERM);
73 CHECK(sethostname(NULL, 65) == -1 && errno == EPERM);
75 CHECK(setdomainname(NULL, 0) == -1 && errno == EPERM);
77 CHECK(setns(-1, CLONE_NEWUTS) == -1 && errno == EBADF);
79 CHECK(setns(saved, CLONE_NEWNS) == -1 && errno == EINVAL);
80 CHECK(ns_path_identity(
"/proc/thread-self/ns/uts", &after) == 0 && ns_same(before, after));
81 CHECK(ns_expect(
"admission",
"admission-domain") == 0);
86static int administrative_credentials(
void) {
87 int failed = 0, saved = -1;
88 struct ns_peer child = NS_PEER_INITIALIZER;
89 saved = open(
"/proc/thread-self/ns/uts", O_RDONLY | O_CLOEXEC);
91 CHECK(ns_spawn(&child, unprivileged, &saved) == 0 && ns_join(&child) == 0);
92 CHECK(ns_expect(
"admission",
"admission-domain") == 0);
95 CHECK(geteuid() == 0 && setfsuid((uid_t)-1) == 1001);
96 CHECK(unshare(CLONE_NEWUTS) == 0 && ns_set(
"admin-fs-override",
"admin-fs-override") == 0);
97 CHECK(setns(saved, 0) == 0 && ns_expect(
"admission",
"admission-domain") == 0);
107static int namespace_capacity(
void) {
108 int failed = 0, original = -1, held[300], count = 0, exhausted = 0;
110 original = open(
"/proc/thread-self/ns/uts", O_RDONLY | O_CLOEXEC);
111 CHECK(original >= 0);
112 while (count < (
int)(
sizeof(held) /
sizeof(held[0]))) {
113 int fd = open(
"/proc/thread-self/ns/uts", O_RDONLY | O_CLOEXEC);
116 CHECK(ns_fd_identity(fd, &before) == 0);
118 if (unshare(CLONE_NEWUTS)) {
119 CHECK(errno == ENOSPC);
120 CHECK(ns_path_identity(
"/proc/thread-self/ns/uts", &after) == 0 && ns_same(before, after));
125 CHECK(exhausted && count > 2);
127 CHECK(close(held[1]) == 0);
129 CHECK(unshare(CLONE_NEWUTS) == 0);
130 CHECK(ns_path_identity(
"/proc/thread-self/ns/uts", &after) == 0 && !ns_same(before, after));
133 if (setns(original, 0))
137 for (
int i = 0; i < count; ++i)
143int ns_admission(
void) {
144 return privileged_failures() || administrative_credentials() || namespace_capacity();