Loading...
Note: File does not exist in v3.5.6.
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
69enum {
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
83const 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
100FIXTURE(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
121static int sys_waitid(int which, pid_t pid, int options)
122{
123 return syscall(__NR_waitid, which, pid, NULL, options, NULL);
124}
125
126pid_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
137static 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
153static 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
164static 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
175FIXTURE_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
407FIXTURE_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
440static 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
452static 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. */
481TEST_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. */
497TEST_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
515TEST_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
551TEST_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
587TEST_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
623TEST_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
667TEST_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
743TEST(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
755TEST_HARNESS_MAIN