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