]> Git Repo - linux.git/blob - tools/testing/selftests/pidfd/pidfd_setns_test.c
x86/kaslr: Expose and use the end of the physical memory address space
[linux.git] / tools / testing / selftests / pidfd / pidfd_setns_test.c
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
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
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
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
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
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
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
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
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
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
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. */
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. */
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
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
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
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
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
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
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
This page took 0.077852 seconds and 4 git commands to generate.