1 // SPDX-License-Identifier: GPL-2.0
2
3 #define _GNU_SOURCE
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <limits.h>
7 #include <linux/types.h>
8 #include <sched.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <syscall.h>
14 #include <sys/prctl.h>
15 #include <sys/wait.h>
16 #include <unistd.h>
17 #include <sys/socket.h>
18 #include <sys/stat.h>
19
20 #include "pidfd.h"
21 #include "../kselftest_harness.h"
22
23 enum {
24 PIDFD_NS_USER,
25 PIDFD_NS_MNT,
26 PIDFD_NS_PID,
27 PIDFD_NS_UTS,
28 PIDFD_NS_IPC,
29 PIDFD_NS_NET,
30 PIDFD_NS_CGROUP,
31 PIDFD_NS_PIDCLD,
32 PIDFD_NS_TIME,
33 PIDFD_NS_TIMECLD,
34 PIDFD_NS_MAX
35 };
36
37 const struct ns_info {
38 const char *name;
39 int flag;
40 unsigned int pidfd_ioctl;
41 } ns_info[] = {
42 [PIDFD_NS_USER] = { "user", CLONE_NEWUSER, PIDFD_GET_USER_NAMESPACE, },
43 [PIDFD_NS_MNT] = { "mnt", CLONE_NEWNS, PIDFD_GET_MNT_NAMESPACE, },
44 [PIDFD_NS_PID] = { "pid", CLONE_NEWPID, PIDFD_GET_PID_NAMESPACE, },
45 [PIDFD_NS_UTS] = { "uts", CLONE_NEWUTS, PIDFD_GET_UTS_NAMESPACE, },
46 [PIDFD_NS_IPC] = { "ipc", CLONE_NEWIPC, PIDFD_GET_IPC_NAMESPACE, },
47 [PIDFD_NS_NET] = { "net", CLONE_NEWNET, PIDFD_GET_NET_NAMESPACE, },
48 [PIDFD_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP, PIDFD_GET_CGROUP_NAMESPACE, },
49 [PIDFD_NS_TIME] = { "time", CLONE_NEWTIME, PIDFD_GET_TIME_NAMESPACE, },
50 [PIDFD_NS_PIDCLD] = { "pid_for_children", 0, PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE, },
51 [PIDFD_NS_TIMECLD] = { "time_for_children", 0, PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE, },
52 };
53
FIXTURE(current_nsset)54 FIXTURE(current_nsset)
55 {
56 pid_t pid;
57 int pidfd;
58 int nsfds[PIDFD_NS_MAX];
59 int child_pidfd_derived_nsfds[PIDFD_NS_MAX];
60
61 pid_t child_pid_exited;
62 int child_pidfd_exited;
63
64 pid_t child_pid1;
65 int child_pidfd1;
66 int child_nsfds1[PIDFD_NS_MAX];
67 int child_pidfd_derived_nsfds1[PIDFD_NS_MAX];
68
69 pid_t child_pid2;
70 int child_pidfd2;
71 int child_nsfds2[PIDFD_NS_MAX];
72 int child_pidfd_derived_nsfds2[PIDFD_NS_MAX];
73 };
74
switch_timens(void)75 static bool switch_timens(void)
76 {
77 int fd, ret;
78
79 if (unshare(CLONE_NEWTIME))
80 return false;
81
82 fd = open("/proc/self/ns/time_for_children", O_RDONLY | O_CLOEXEC);
83 if (fd < 0)
84 return false;
85
86 ret = setns(fd, CLONE_NEWTIME);
87 close(fd);
88 return ret == 0;
89 }
90
FIXTURE_SETUP(current_nsset)91 FIXTURE_SETUP(current_nsset)
92 {
93 int i, proc_fd, ret;
94 int ipc_sockets[2];
95 char c;
96
97 for (i = 0; i < PIDFD_NS_MAX; i++) {
98 self->nsfds[i] = -EBADF;
99 self->child_nsfds1[i] = -EBADF;
100 self->child_nsfds2[i] = -EBADF;
101 self->child_pidfd_derived_nsfds[i] = -EBADF;
102 self->child_pidfd_derived_nsfds1[i] = -EBADF;
103 self->child_pidfd_derived_nsfds2[i] = -EBADF;
104 }
105
106 proc_fd = open("/proc/self/ns", O_DIRECTORY | O_CLOEXEC);
107 ASSERT_GE(proc_fd, 0) {
108 TH_LOG("%m - Failed to open /proc/self/ns");
109 }
110
111 self->pid = getpid();
112 self->pidfd = sys_pidfd_open(self->pid, 0);
113 EXPECT_GT(self->pidfd, 0) {
114 TH_LOG("%m - Failed to open pidfd for process %d", self->pid);
115 }
116
117 for (i = 0; i < PIDFD_NS_MAX; i++) {
118 const struct ns_info *info = &ns_info[i];
119 self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC);
120 if (self->nsfds[i] < 0) {
121 EXPECT_EQ(errno, ENOENT) {
122 TH_LOG("%m - Failed to open %s namespace for process %d",
123 info->name, self->pid);
124 }
125 }
126
127 self->child_pidfd_derived_nsfds[i] = ioctl(self->pidfd, info->pidfd_ioctl, 0);
128 if (self->child_pidfd_derived_nsfds[i] < 0) {
129 EXPECT_EQ(errno, EOPNOTSUPP) {
130 TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
131 info->name, self->pid);
132 }
133 }
134 }
135
136 /* Create task that exits right away. */
137 self->child_pid_exited = create_child(&self->child_pidfd_exited, 0);
138 EXPECT_GE(self->child_pid_exited, 0);
139
140 if (self->child_pid_exited == 0) {
141 if (self->nsfds[PIDFD_NS_USER] >= 0 && unshare(CLONE_NEWUSER) < 0)
142 _exit(EXIT_FAILURE);
143 if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0)
144 _exit(EXIT_FAILURE);
145 _exit(EXIT_SUCCESS);
146 }
147
148 ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, NULL, WEXITED | WNOWAIT), 0);
149
150 self->pidfd = sys_pidfd_open(self->pid, 0);
151 EXPECT_GE(self->pidfd, 0) {
152 TH_LOG("%m - Failed to open pidfd for process %d", self->pid);
153 }
154
155 ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
156 EXPECT_EQ(ret, 0);
157
158 /* Create tasks that will be stopped. */
159 if (self->nsfds[PIDFD_NS_USER] >= 0 && self->nsfds[PIDFD_NS_PID] >= 0)
160 self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER | CLONE_NEWPID);
161 else if (self->nsfds[PIDFD_NS_PID] >= 0)
162 self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWPID);
163 else if (self->nsfds[PIDFD_NS_USER] >= 0)
164 self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER);
165 else
166 self->child_pid1 = create_child(&self->child_pidfd1, 0);
167 EXPECT_GE(self->child_pid1, 0);
168
169 if (self->child_pid1 == 0) {
170 close(ipc_sockets[0]);
171
172 if (self->nsfds[PIDFD_NS_MNT] >= 0 && unshare(CLONE_NEWNS) < 0) {
173 TH_LOG("%m - Failed to unshare mount namespace for process %d", self->pid);
174 _exit(EXIT_FAILURE);
175 }
176 if (self->nsfds[PIDFD_NS_CGROUP] >= 0 && unshare(CLONE_NEWCGROUP) < 0) {
177 TH_LOG("%m - Failed to unshare cgroup namespace for process %d", self->pid);
178 _exit(EXIT_FAILURE);
179 }
180 if (self->nsfds[PIDFD_NS_IPC] >= 0 && unshare(CLONE_NEWIPC) < 0) {
181 TH_LOG("%m - Failed to unshare ipc namespace for process %d", self->pid);
182 _exit(EXIT_FAILURE);
183 }
184 if (self->nsfds[PIDFD_NS_UTS] >= 0 && unshare(CLONE_NEWUTS) < 0) {
185 TH_LOG("%m - Failed to unshare uts namespace for process %d", self->pid);
186 _exit(EXIT_FAILURE);
187 }
188 if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) {
189 TH_LOG("%m - Failed to unshare net namespace for process %d", self->pid);
190 _exit(EXIT_FAILURE);
191 }
192 if (self->nsfds[PIDFD_NS_TIME] >= 0 && !switch_timens()) {
193 TH_LOG("%m - Failed to unshare time namespace for process %d", self->pid);
194 _exit(EXIT_FAILURE);
195 }
196
197 if (write_nointr(ipc_sockets[1], "1", 1) < 0)
198 _exit(EXIT_FAILURE);
199
200 close(ipc_sockets[1]);
201
202 pause();
203 _exit(EXIT_SUCCESS);
204 }
205
206 close(ipc_sockets[1]);
207 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
208 close(ipc_sockets[0]);
209
210 ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
211 EXPECT_EQ(ret, 0);
212
213 if (self->nsfds[PIDFD_NS_USER] >= 0 && self->nsfds[PIDFD_NS_PID] >= 0)
214 self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER | CLONE_NEWPID);
215 else if (self->nsfds[PIDFD_NS_PID] >= 0)
216 self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWPID);
217 else if (self->nsfds[PIDFD_NS_USER] >= 0)
218 self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER);
219 else
220 self->child_pid2 = create_child(&self->child_pidfd2, 0);
221 EXPECT_GE(self->child_pid2, 0);
222
223 if (self->child_pid2 == 0) {
224 close(ipc_sockets[0]);
225
226 if (self->nsfds[PIDFD_NS_MNT] >= 0 && unshare(CLONE_NEWNS) < 0) {
227 TH_LOG("%m - Failed to unshare mount namespace for process %d", self->pid);
228 _exit(EXIT_FAILURE);
229 }
230 if (self->nsfds[PIDFD_NS_CGROUP] >= 0 && unshare(CLONE_NEWCGROUP) < 0) {
231 TH_LOG("%m - Failed to unshare cgroup namespace for process %d", self->pid);
232 _exit(EXIT_FAILURE);
233 }
234 if (self->nsfds[PIDFD_NS_IPC] >= 0 && unshare(CLONE_NEWIPC) < 0) {
235 TH_LOG("%m - Failed to unshare ipc namespace for process %d", self->pid);
236 _exit(EXIT_FAILURE);
237 }
238 if (self->nsfds[PIDFD_NS_UTS] >= 0 && unshare(CLONE_NEWUTS) < 0) {
239 TH_LOG("%m - Failed to unshare uts namespace for process %d", self->pid);
240 _exit(EXIT_FAILURE);
241 }
242 if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) {
243 TH_LOG("%m - Failed to unshare net namespace for process %d", self->pid);
244 _exit(EXIT_FAILURE);
245 }
246 if (self->nsfds[PIDFD_NS_TIME] >= 0 && !switch_timens()) {
247 TH_LOG("%m - Failed to unshare time namespace for process %d", self->pid);
248 _exit(EXIT_FAILURE);
249 }
250
251 if (write_nointr(ipc_sockets[1], "1", 1) < 0)
252 _exit(EXIT_FAILURE);
253
254 close(ipc_sockets[1]);
255
256 pause();
257 _exit(EXIT_SUCCESS);
258 }
259
260 close(ipc_sockets[1]);
261 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
262 close(ipc_sockets[0]);
263
264 for (i = 0; i < PIDFD_NS_MAX; i++) {
265 char p[100];
266
267 const struct ns_info *info = &ns_info[i];
268
269 self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC);
270 if (self->nsfds[i] < 0) {
271 EXPECT_EQ(errno, ENOENT) {
272 TH_LOG("%m - Failed to open %s namespace for process %d",
273 info->name, self->pid);
274 }
275 }
276
277 ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s",
278 self->child_pid1, info->name);
279 EXPECT_GT(ret, 0);
280 EXPECT_LT(ret, sizeof(p));
281
282 self->child_nsfds1[i] = open(p, O_RDONLY | O_CLOEXEC);
283 if (self->child_nsfds1[i] < 0) {
284 EXPECT_EQ(errno, ENOENT) {
285 TH_LOG("%m - Failed to open %s namespace for process %d",
286 info->name, self->child_pid1);
287 }
288 }
289
290 ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s",
291 self->child_pid2, info->name);
292 EXPECT_GT(ret, 0);
293 EXPECT_LT(ret, sizeof(p));
294
295 self->child_nsfds2[i] = open(p, O_RDONLY | O_CLOEXEC);
296 if (self->child_nsfds2[i] < 0) {
297 EXPECT_EQ(errno, ENOENT) {
298 TH_LOG("%m - Failed to open %s namespace for process %d",
299 info->name, self->child_pid1);
300 }
301 }
302
303 self->child_pidfd_derived_nsfds1[i] = ioctl(self->child_pidfd1, info->pidfd_ioctl, 0);
304 if (self->child_pidfd_derived_nsfds1[i] < 0) {
305 EXPECT_EQ(errno, EOPNOTSUPP) {
306 TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
307 info->name, self->child_pid1);
308 }
309 }
310
311 self->child_pidfd_derived_nsfds2[i] = ioctl(self->child_pidfd2, info->pidfd_ioctl, 0);
312 if (self->child_pidfd_derived_nsfds2[i] < 0) {
313 EXPECT_EQ(errno, EOPNOTSUPP) {
314 TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
315 info->name, self->child_pid2);
316 }
317 }
318 }
319
320 close(proc_fd);
321 }
322
FIXTURE_TEARDOWN(current_nsset)323 FIXTURE_TEARDOWN(current_nsset)
324 {
325 int i;
326
327 ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd1,
328 SIGKILL, NULL, 0), 0);
329 ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd2,
330 SIGKILL, NULL, 0), 0);
331
332 for (i = 0; i < PIDFD_NS_MAX; i++) {
333 if (self->nsfds[i] >= 0)
334 close(self->nsfds[i]);
335 if (self->child_nsfds1[i] >= 0)
336 close(self->child_nsfds1[i]);
337 if (self->child_nsfds2[i] >= 0)
338 close(self->child_nsfds2[i]);
339 if (self->child_pidfd_derived_nsfds[i] >= 0)
340 close(self->child_pidfd_derived_nsfds[i]);
341 if (self->child_pidfd_derived_nsfds1[i] >= 0)
342 close(self->child_pidfd_derived_nsfds1[i]);
343 if (self->child_pidfd_derived_nsfds2[i] >= 0)
344 close(self->child_pidfd_derived_nsfds2[i]);
345 }
346
347 if (self->child_pidfd1 >= 0)
348 EXPECT_EQ(0, close(self->child_pidfd1));
349 if (self->child_pidfd2 >= 0)
350 EXPECT_EQ(0, close(self->child_pidfd2));
351 ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, NULL, WEXITED), 0);
352 ASSERT_EQ(sys_waitid(P_PID, self->child_pid1, NULL, WEXITED), 0);
353 ASSERT_EQ(sys_waitid(P_PID, self->child_pid2, NULL, WEXITED), 0);
354 }
355
preserve_ns(const int pid,const char * ns)356 static int preserve_ns(const int pid, const char *ns)
357 {
358 int ret;
359 char path[50];
360
361 ret = snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns);
362 if (ret < 0 || (size_t)ret >= sizeof(path))
363 return -EIO;
364
365 return open(path, O_RDONLY | O_CLOEXEC);
366 }
367
in_same_namespace(int ns_fd1,pid_t pid2,const char * ns)368 static int in_same_namespace(int ns_fd1, pid_t pid2, const char *ns)
369 {
370 int ns_fd2 = -EBADF;
371 int ret = -1;
372 struct stat ns_st1, ns_st2;
373
374 ret = fstat(ns_fd1, &ns_st1);
375 if (ret < 0)
376 return -1;
377
378 ns_fd2 = preserve_ns(pid2, ns);
379 if (ns_fd2 < 0)
380 return -1;
381
382 ret = fstat(ns_fd2, &ns_st2);
383 close(ns_fd2);
384 if (ret < 0)
385 return -1;
386
387 /* processes are in the same namespace */
388 if ((ns_st1.st_dev == ns_st2.st_dev) &&
389 (ns_st1.st_ino == ns_st2.st_ino))
390 return 1;
391
392 /* processes are in different namespaces */
393 return 0;
394 }
395
396 /* Test that we can't pass garbage to the kernel. */
TEST_F(current_nsset,invalid_flags)397 TEST_F(current_nsset, invalid_flags)
398 {
399 ASSERT_NE(setns(self->pidfd, 0), 0);
400 EXPECT_EQ(errno, EINVAL);
401
402 ASSERT_NE(setns(self->pidfd, -1), 0);
403 EXPECT_EQ(errno, EINVAL);
404
405 ASSERT_NE(setns(self->pidfd, CLONE_VM), 0);
406 EXPECT_EQ(errno, EINVAL);
407
408 ASSERT_NE(setns(self->pidfd, CLONE_NEWUSER | CLONE_VM), 0);
409 EXPECT_EQ(errno, EINVAL);
410 }
411
412 /* Test that we can't attach to a task that has already exited. */
TEST_F(current_nsset,pidfd_exited_child)413 TEST_F(current_nsset, pidfd_exited_child)
414 {
415 int i;
416 pid_t pid;
417
418 ASSERT_NE(setns(self->child_pidfd_exited, CLONE_NEWUSER | CLONE_NEWNET),
419 0);
420 EXPECT_EQ(errno, ESRCH);
421
422 pid = getpid();
423 for (i = 0; i < PIDFD_NS_MAX; i++) {
424 const struct ns_info *info = &ns_info[i];
425 /* Verify that we haven't changed any namespaces. */
426 if (self->nsfds[i] >= 0)
427 ASSERT_EQ(in_same_namespace(self->nsfds[i], pid, info->name), 1);
428 }
429 }
430
TEST_F(current_nsset,pidfd_incremental_setns)431 TEST_F(current_nsset, pidfd_incremental_setns)
432 {
433 int i;
434 pid_t pid;
435
436 pid = getpid();
437 for (i = 0; i < PIDFD_NS_MAX; i++) {
438 const struct ns_info *info = &ns_info[i];
439 int nsfd;
440
441 if (self->child_nsfds1[i] < 0)
442 continue;
443
444 if (info->flag) {
445 ASSERT_EQ(setns(self->child_pidfd1, info->flag), 0) {
446 TH_LOG("%m - Failed to setns to %s namespace of %d via pidfd %d",
447 info->name, self->child_pid1,
448 self->child_pidfd1);
449 }
450 }
451
452 /* Verify that we have changed to the correct namespaces. */
453 if (info->flag == CLONE_NEWPID)
454 nsfd = self->nsfds[i];
455 else
456 nsfd = self->child_nsfds1[i];
457 ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
458 TH_LOG("setns failed to place us correctly into %s namespace of %d via pidfd %d",
459 info->name, self->child_pid1,
460 self->child_pidfd1);
461 }
462 TH_LOG("Managed to correctly setns to %s namespace of %d via pidfd %d",
463 info->name, self->child_pid1, self->child_pidfd1);
464 }
465 }
466
TEST_F(current_nsset,nsfd_incremental_setns)467 TEST_F(current_nsset, nsfd_incremental_setns)
468 {
469 int i;
470 pid_t pid;
471
472 pid = getpid();
473 for (i = 0; i < PIDFD_NS_MAX; i++) {
474 const struct ns_info *info = &ns_info[i];
475 int nsfd;
476
477 if (self->child_nsfds1[i] < 0)
478 continue;
479
480 if (info->flag) {
481 ASSERT_EQ(setns(self->child_nsfds1[i], info->flag), 0) {
482 TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d",
483 info->name, self->child_pid1,
484 self->child_nsfds1[i]);
485 }
486 }
487
488 /* Verify that we have changed to the correct namespaces. */
489 if (info->flag == CLONE_NEWPID)
490 nsfd = self->nsfds[i];
491 else
492 nsfd = self->child_nsfds1[i];
493 ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
494 TH_LOG("setns failed to place us correctly into %s namespace of %d via nsfd %d",
495 info->name, self->child_pid1,
496 self->child_nsfds1[i]);
497 }
498 TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d",
499 info->name, self->child_pid1, self->child_nsfds1[i]);
500 }
501 }
502
TEST_F(current_nsset,pidfd_derived_nsfd_incremental_setns)503 TEST_F(current_nsset, pidfd_derived_nsfd_incremental_setns)
504 {
505 int i;
506 pid_t pid;
507
508 pid = getpid();
509 for (i = 0; i < PIDFD_NS_MAX; i++) {
510 const struct ns_info *info = &ns_info[i];
511 int nsfd;
512
513 if (self->child_pidfd_derived_nsfds1[i] < 0)
514 continue;
515
516 if (info->flag) {
517 ASSERT_EQ(setns(self->child_pidfd_derived_nsfds1[i], info->flag), 0) {
518 TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d",
519 info->name, self->child_pid1,
520 self->child_pidfd_derived_nsfds1[i]);
521 }
522 }
523
524 /* Verify that we have changed to the correct namespaces. */
525 if (info->flag == CLONE_NEWPID)
526 nsfd = self->child_pidfd_derived_nsfds[i];
527 else
528 nsfd = self->child_pidfd_derived_nsfds1[i];
529 ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
530 TH_LOG("setns failed to place us correctly into %s namespace of %d via nsfd %d",
531 info->name, self->child_pid1,
532 self->child_pidfd_derived_nsfds1[i]);
533 }
534 TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d",
535 info->name, self->child_pid1, self->child_pidfd_derived_nsfds1[i]);
536 }
537 }
538
TEST_F(current_nsset,pidfd_one_shot_setns)539 TEST_F(current_nsset, pidfd_one_shot_setns)
540 {
541 unsigned flags = 0;
542 int i;
543 pid_t pid;
544
545 for (i = 0; i < PIDFD_NS_MAX; i++) {
546 const struct ns_info *info = &ns_info[i];
547
548 if (self->child_nsfds1[i] < 0)
549 continue;
550
551 flags |= info->flag;
552 TH_LOG("Adding %s namespace of %d to list of namespaces to attach to",
553 info->name, self->child_pid1);
554 }
555
556 ASSERT_EQ(setns(self->child_pidfd1, flags), 0) {
557 TH_LOG("%m - Failed to setns to namespaces of %d",
558 self->child_pid1);
559 }
560
561 pid = getpid();
562 for (i = 0; i < PIDFD_NS_MAX; i++) {
563 const struct ns_info *info = &ns_info[i];
564 int nsfd;
565
566 if (self->child_nsfds1[i] < 0)
567 continue;
568
569 /* Verify that we have changed to the correct namespaces. */
570 if (info->flag == CLONE_NEWPID)
571 nsfd = self->nsfds[i];
572 else
573 nsfd = self->child_nsfds1[i];
574 ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
575 TH_LOG("setns failed to place us correctly into %s namespace of %d",
576 info->name, self->child_pid1);
577 }
578 TH_LOG("Managed to correctly setns to %s namespace of %d",
579 info->name, self->child_pid1);
580 }
581 }
582
TEST_F(current_nsset,no_foul_play)583 TEST_F(current_nsset, no_foul_play)
584 {
585 unsigned flags = 0;
586 int i;
587
588 for (i = 0; i < PIDFD_NS_MAX; i++) {
589 const struct ns_info *info = &ns_info[i];
590
591 if (self->child_nsfds1[i] < 0)
592 continue;
593
594 flags |= info->flag;
595 if (info->flag) /* No use logging pid_for_children. */
596 TH_LOG("Adding %s namespace of %d to list of namespaces to attach to",
597 info->name, self->child_pid1);
598 }
599
600 ASSERT_EQ(setns(self->child_pidfd1, flags), 0) {
601 TH_LOG("%m - Failed to setns to namespaces of %d vid pidfd %d",
602 self->child_pid1, self->child_pidfd1);
603 }
604
605 /*
606 * Can't setns to a user namespace outside of our hierarchy since we
607 * don't have caps in there and didn't create it. That means that under
608 * no circumstances should we be able to setns to any of the other
609 * ones since they aren't owned by our user namespace.
610 */
611 for (i = 0; i < PIDFD_NS_MAX; i++) {
612 const struct ns_info *info = &ns_info[i];
613
614 if (self->child_nsfds2[i] < 0 || !info->flag)
615 continue;
616
617 ASSERT_NE(setns(self->child_pidfd2, info->flag), 0) {
618 TH_LOG("Managed to setns to %s namespace of %d via pidfd %d",
619 info->name, self->child_pid2,
620 self->child_pidfd2);
621 }
622 TH_LOG("%m - Correctly failed to setns to %s namespace of %d via pidfd %d",
623 info->name, self->child_pid2,
624 self->child_pidfd2);
625
626 ASSERT_NE(setns(self->child_nsfds2[i], info->flag), 0) {
627 TH_LOG("Managed to setns to %s namespace of %d via nsfd %d",
628 info->name, self->child_pid2,
629 self->child_nsfds2[i]);
630 }
631 TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d",
632 info->name, self->child_pid2,
633 self->child_nsfds2[i]);
634 }
635
636 /*
637 * Can't setns to a user namespace outside of our hierarchy since we
638 * don't have caps in there and didn't create it. That means that under
639 * no circumstances should we be able to setns to any of the other
640 * ones since they aren't owned by our user namespace.
641 */
642 for (i = 0; i < PIDFD_NS_MAX; i++) {
643 const struct ns_info *info = &ns_info[i];
644
645 if (self->child_pidfd_derived_nsfds2[i] < 0 || !info->flag)
646 continue;
647
648 ASSERT_NE(setns(self->child_pidfd_derived_nsfds2[i], info->flag), 0) {
649 TH_LOG("Managed to setns to %s namespace of %d via nsfd %d",
650 info->name, self->child_pid2,
651 self->child_pidfd_derived_nsfds2[i]);
652 }
653 TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d",
654 info->name, self->child_pid2,
655 self->child_pidfd_derived_nsfds2[i]);
656 }
657 }
658
TEST(setns_einval)659 TEST(setns_einval)
660 {
661 int fd;
662
663 fd = sys_memfd_create("rostock", 0);
664 EXPECT_GT(fd, 0);
665
666 ASSERT_NE(setns(fd, 0), 0);
667 EXPECT_EQ(errno, EINVAL);
668 close(fd);
669 }
670
671 TEST_HARNESS_MAIN
672