~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/pidfd/pidfd_setns_test.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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
756 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php