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