1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun #define _GNU_SOURCE
4*4882a593Smuzhiyun #include <errno.h>
5*4882a593Smuzhiyun #include <fcntl.h>
6*4882a593Smuzhiyun #include <limits.h>
7*4882a593Smuzhiyun #include <linux/types.h>
8*4882a593Smuzhiyun #include <sched.h>
9*4882a593Smuzhiyun #include <signal.h>
10*4882a593Smuzhiyun #include <stdio.h>
11*4882a593Smuzhiyun #include <stdlib.h>
12*4882a593Smuzhiyun #include <string.h>
13*4882a593Smuzhiyun #include <syscall.h>
14*4882a593Smuzhiyun #include <sys/prctl.h>
15*4882a593Smuzhiyun #include <sys/wait.h>
16*4882a593Smuzhiyun #include <unistd.h>
17*4882a593Smuzhiyun #include <sys/socket.h>
18*4882a593Smuzhiyun #include <sys/stat.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include "pidfd.h"
21*4882a593Smuzhiyun #include "../clone3/clone3_selftests.h"
22*4882a593Smuzhiyun #include "../kselftest_harness.h"
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun enum {
25*4882a593Smuzhiyun PIDFD_NS_USER,
26*4882a593Smuzhiyun PIDFD_NS_MNT,
27*4882a593Smuzhiyun PIDFD_NS_PID,
28*4882a593Smuzhiyun PIDFD_NS_UTS,
29*4882a593Smuzhiyun PIDFD_NS_IPC,
30*4882a593Smuzhiyun PIDFD_NS_NET,
31*4882a593Smuzhiyun PIDFD_NS_CGROUP,
32*4882a593Smuzhiyun PIDFD_NS_PIDCLD,
33*4882a593Smuzhiyun PIDFD_NS_TIME,
34*4882a593Smuzhiyun PIDFD_NS_MAX
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun const struct ns_info {
38*4882a593Smuzhiyun const char *name;
39*4882a593Smuzhiyun int flag;
40*4882a593Smuzhiyun } ns_info[] = {
41*4882a593Smuzhiyun [PIDFD_NS_USER] = { "user", CLONE_NEWUSER, },
42*4882a593Smuzhiyun [PIDFD_NS_MNT] = { "mnt", CLONE_NEWNS, },
43*4882a593Smuzhiyun [PIDFD_NS_PID] = { "pid", CLONE_NEWPID, },
44*4882a593Smuzhiyun [PIDFD_NS_UTS] = { "uts", CLONE_NEWUTS, },
45*4882a593Smuzhiyun [PIDFD_NS_IPC] = { "ipc", CLONE_NEWIPC, },
46*4882a593Smuzhiyun [PIDFD_NS_NET] = { "net", CLONE_NEWNET, },
47*4882a593Smuzhiyun [PIDFD_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP, },
48*4882a593Smuzhiyun [PIDFD_NS_PIDCLD] = { "pid_for_children", 0, },
49*4882a593Smuzhiyun [PIDFD_NS_TIME] = { "time", CLONE_NEWTIME, },
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun
FIXTURE(current_nsset)52*4882a593Smuzhiyun FIXTURE(current_nsset)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun pid_t pid;
55*4882a593Smuzhiyun int pidfd;
56*4882a593Smuzhiyun int nsfds[PIDFD_NS_MAX];
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun pid_t child_pid_exited;
59*4882a593Smuzhiyun int child_pidfd_exited;
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun pid_t child_pid1;
62*4882a593Smuzhiyun int child_pidfd1;
63*4882a593Smuzhiyun int child_nsfds1[PIDFD_NS_MAX];
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun pid_t child_pid2;
66*4882a593Smuzhiyun int child_pidfd2;
67*4882a593Smuzhiyun int child_nsfds2[PIDFD_NS_MAX];
68*4882a593Smuzhiyun };
69*4882a593Smuzhiyun
sys_waitid(int which,pid_t pid,int options)70*4882a593Smuzhiyun static int sys_waitid(int which, pid_t pid, int options)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun return syscall(__NR_waitid, which, pid, NULL, options, NULL);
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
create_child(int * pidfd,unsigned flags)75*4882a593Smuzhiyun pid_t create_child(int *pidfd, unsigned flags)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun struct __clone_args args = {
78*4882a593Smuzhiyun .flags = CLONE_PIDFD | flags,
79*4882a593Smuzhiyun .exit_signal = SIGCHLD,
80*4882a593Smuzhiyun .pidfd = ptr_to_u64(pidfd),
81*4882a593Smuzhiyun };
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun return sys_clone3(&args, sizeof(struct clone_args));
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
switch_timens(void)86*4882a593Smuzhiyun static bool switch_timens(void)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun int fd, ret;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun if (unshare(CLONE_NEWTIME))
91*4882a593Smuzhiyun return false;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun fd = open("/proc/self/ns/time_for_children", O_RDONLY | O_CLOEXEC);
94*4882a593Smuzhiyun if (fd < 0)
95*4882a593Smuzhiyun return false;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun ret = setns(fd, CLONE_NEWTIME);
98*4882a593Smuzhiyun close(fd);
99*4882a593Smuzhiyun return ret == 0;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
read_nointr(int fd,void * buf,size_t count)102*4882a593Smuzhiyun static ssize_t read_nointr(int fd, void *buf, size_t count)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun ssize_t ret;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun do {
107*4882a593Smuzhiyun ret = read(fd, buf, count);
108*4882a593Smuzhiyun } while (ret < 0 && errno == EINTR);
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun return ret;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun
write_nointr(int fd,const void * buf,size_t count)113*4882a593Smuzhiyun static ssize_t write_nointr(int fd, const void *buf, size_t count)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun ssize_t ret;
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun do {
118*4882a593Smuzhiyun ret = write(fd, buf, count);
119*4882a593Smuzhiyun } while (ret < 0 && errno == EINTR);
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun return ret;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
FIXTURE_SETUP(current_nsset)124*4882a593Smuzhiyun FIXTURE_SETUP(current_nsset)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun int i, proc_fd, ret;
127*4882a593Smuzhiyun int ipc_sockets[2];
128*4882a593Smuzhiyun char c;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun for (i = 0; i < PIDFD_NS_MAX; i++) {
131*4882a593Smuzhiyun self->nsfds[i] = -EBADF;
132*4882a593Smuzhiyun self->child_nsfds1[i] = -EBADF;
133*4882a593Smuzhiyun self->child_nsfds2[i] = -EBADF;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun proc_fd = open("/proc/self/ns", O_DIRECTORY | O_CLOEXEC);
137*4882a593Smuzhiyun ASSERT_GE(proc_fd, 0) {
138*4882a593Smuzhiyun TH_LOG("%m - Failed to open /proc/self/ns");
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun self->pid = getpid();
142*4882a593Smuzhiyun for (i = 0; i < PIDFD_NS_MAX; i++) {
143*4882a593Smuzhiyun const struct ns_info *info = &ns_info[i];
144*4882a593Smuzhiyun self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC);
145*4882a593Smuzhiyun if (self->nsfds[i] < 0) {
146*4882a593Smuzhiyun EXPECT_EQ(errno, ENOENT) {
147*4882a593Smuzhiyun TH_LOG("%m - Failed to open %s namespace for process %d",
148*4882a593Smuzhiyun info->name, self->pid);
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun self->pidfd = sys_pidfd_open(self->pid, 0);
154*4882a593Smuzhiyun EXPECT_GT(self->pidfd, 0) {
155*4882a593Smuzhiyun TH_LOG("%m - Failed to open pidfd for process %d", self->pid);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /* Create task that exits right away. */
159*4882a593Smuzhiyun self->child_pid_exited = create_child(&self->child_pidfd_exited,
160*4882a593Smuzhiyun CLONE_NEWUSER | CLONE_NEWNET);
161*4882a593Smuzhiyun EXPECT_GT(self->child_pid_exited, 0);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun if (self->child_pid_exited == 0)
164*4882a593Smuzhiyun _exit(EXIT_SUCCESS);
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, WEXITED | WNOWAIT), 0);
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun self->pidfd = sys_pidfd_open(self->pid, 0);
169*4882a593Smuzhiyun EXPECT_GE(self->pidfd, 0) {
170*4882a593Smuzhiyun TH_LOG("%m - Failed to open pidfd for process %d", self->pid);
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
174*4882a593Smuzhiyun EXPECT_EQ(ret, 0);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /* Create tasks that will be stopped. */
177*4882a593Smuzhiyun self->child_pid1 = create_child(&self->child_pidfd1,
178*4882a593Smuzhiyun CLONE_NEWUSER | CLONE_NEWNS |
179*4882a593Smuzhiyun CLONE_NEWCGROUP | CLONE_NEWIPC |
180*4882a593Smuzhiyun CLONE_NEWUTS | CLONE_NEWPID |
181*4882a593Smuzhiyun CLONE_NEWNET);
182*4882a593Smuzhiyun EXPECT_GE(self->child_pid1, 0);
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun if (self->child_pid1 == 0) {
185*4882a593Smuzhiyun close(ipc_sockets[0]);
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun if (!switch_timens())
188*4882a593Smuzhiyun _exit(EXIT_FAILURE);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun if (write_nointr(ipc_sockets[1], "1", 1) < 0)
191*4882a593Smuzhiyun _exit(EXIT_FAILURE);
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun close(ipc_sockets[1]);
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun pause();
196*4882a593Smuzhiyun _exit(EXIT_SUCCESS);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun close(ipc_sockets[1]);
200*4882a593Smuzhiyun ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
201*4882a593Smuzhiyun close(ipc_sockets[0]);
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
204*4882a593Smuzhiyun EXPECT_EQ(ret, 0);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun self->child_pid2 = create_child(&self->child_pidfd2,
207*4882a593Smuzhiyun CLONE_NEWUSER | CLONE_NEWNS |
208*4882a593Smuzhiyun CLONE_NEWCGROUP | CLONE_NEWIPC |
209*4882a593Smuzhiyun CLONE_NEWUTS | CLONE_NEWPID |
210*4882a593Smuzhiyun CLONE_NEWNET);
211*4882a593Smuzhiyun EXPECT_GE(self->child_pid2, 0);
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if (self->child_pid2 == 0) {
214*4882a593Smuzhiyun close(ipc_sockets[0]);
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun if (!switch_timens())
217*4882a593Smuzhiyun _exit(EXIT_FAILURE);
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun if (write_nointr(ipc_sockets[1], "1", 1) < 0)
220*4882a593Smuzhiyun _exit(EXIT_FAILURE);
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun close(ipc_sockets[1]);
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun pause();
225*4882a593Smuzhiyun _exit(EXIT_SUCCESS);
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun close(ipc_sockets[1]);
229*4882a593Smuzhiyun ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
230*4882a593Smuzhiyun close(ipc_sockets[0]);
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun for (i = 0; i < PIDFD_NS_MAX; i++) {
233*4882a593Smuzhiyun char p[100];
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun const struct ns_info *info = &ns_info[i];
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC);
238*4882a593Smuzhiyun if (self->nsfds[i] < 0) {
239*4882a593Smuzhiyun EXPECT_EQ(errno, ENOENT) {
240*4882a593Smuzhiyun TH_LOG("%m - Failed to open %s namespace for process %d",
241*4882a593Smuzhiyun info->name, self->pid);
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s",
246*4882a593Smuzhiyun self->child_pid1, info->name);
247*4882a593Smuzhiyun EXPECT_GT(ret, 0);
248*4882a593Smuzhiyun EXPECT_LT(ret, sizeof(p));
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun self->child_nsfds1[i] = open(p, O_RDONLY | O_CLOEXEC);
251*4882a593Smuzhiyun if (self->child_nsfds1[i] < 0) {
252*4882a593Smuzhiyun EXPECT_EQ(errno, ENOENT) {
253*4882a593Smuzhiyun TH_LOG("%m - Failed to open %s namespace for process %d",
254*4882a593Smuzhiyun info->name, self->child_pid1);
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s",
259*4882a593Smuzhiyun self->child_pid2, info->name);
260*4882a593Smuzhiyun EXPECT_GT(ret, 0);
261*4882a593Smuzhiyun EXPECT_LT(ret, sizeof(p));
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun self->child_nsfds2[i] = open(p, O_RDONLY | O_CLOEXEC);
264*4882a593Smuzhiyun if (self->child_nsfds2[i] < 0) {
265*4882a593Smuzhiyun EXPECT_EQ(errno, ENOENT) {
266*4882a593Smuzhiyun TH_LOG("%m - Failed to open %s namespace for process %d",
267*4882a593Smuzhiyun info->name, self->child_pid1);
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun close(proc_fd);
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
FIXTURE_TEARDOWN(current_nsset)275*4882a593Smuzhiyun FIXTURE_TEARDOWN(current_nsset)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun int i;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd1,
280*4882a593Smuzhiyun SIGKILL, NULL, 0), 0);
281*4882a593Smuzhiyun ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd2,
282*4882a593Smuzhiyun SIGKILL, NULL, 0), 0);
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun for (i = 0; i < PIDFD_NS_MAX; i++) {
285*4882a593Smuzhiyun if (self->nsfds[i] >= 0)
286*4882a593Smuzhiyun close(self->nsfds[i]);
287*4882a593Smuzhiyun if (self->child_nsfds1[i] >= 0)
288*4882a593Smuzhiyun close(self->child_nsfds1[i]);
289*4882a593Smuzhiyun if (self->child_nsfds2[i] >= 0)
290*4882a593Smuzhiyun close(self->child_nsfds2[i]);
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun if (self->child_pidfd1 >= 0)
294*4882a593Smuzhiyun EXPECT_EQ(0, close(self->child_pidfd1));
295*4882a593Smuzhiyun if (self->child_pidfd2 >= 0)
296*4882a593Smuzhiyun EXPECT_EQ(0, close(self->child_pidfd2));
297*4882a593Smuzhiyun ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, WEXITED), 0);
298*4882a593Smuzhiyun ASSERT_EQ(sys_waitid(P_PID, self->child_pid1, WEXITED), 0);
299*4882a593Smuzhiyun ASSERT_EQ(sys_waitid(P_PID, self->child_pid2, WEXITED), 0);
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
preserve_ns(const int pid,const char * ns)302*4882a593Smuzhiyun static int preserve_ns(const int pid, const char *ns)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun int ret;
305*4882a593Smuzhiyun char path[50];
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun ret = snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns);
308*4882a593Smuzhiyun if (ret < 0 || (size_t)ret >= sizeof(path))
309*4882a593Smuzhiyun return -EIO;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun return open(path, O_RDONLY | O_CLOEXEC);
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
in_same_namespace(int ns_fd1,pid_t pid2,const char * ns)314*4882a593Smuzhiyun static int in_same_namespace(int ns_fd1, pid_t pid2, const char *ns)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun int ns_fd2 = -EBADF;
317*4882a593Smuzhiyun int ret = -1;
318*4882a593Smuzhiyun struct stat ns_st1, ns_st2;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun ret = fstat(ns_fd1, &ns_st1);
321*4882a593Smuzhiyun if (ret < 0)
322*4882a593Smuzhiyun return -1;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun ns_fd2 = preserve_ns(pid2, ns);
325*4882a593Smuzhiyun if (ns_fd2 < 0)
326*4882a593Smuzhiyun return -1;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun ret = fstat(ns_fd2, &ns_st2);
329*4882a593Smuzhiyun close(ns_fd2);
330*4882a593Smuzhiyun if (ret < 0)
331*4882a593Smuzhiyun return -1;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun /* processes are in the same namespace */
334*4882a593Smuzhiyun if ((ns_st1.st_dev == ns_st2.st_dev) &&
335*4882a593Smuzhiyun (ns_st1.st_ino == ns_st2.st_ino))
336*4882a593Smuzhiyun return 1;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun /* processes are in different namespaces */
339*4882a593Smuzhiyun return 0;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun /* Test that we can't pass garbage to the kernel. */
TEST_F(current_nsset,invalid_flags)343*4882a593Smuzhiyun TEST_F(current_nsset, invalid_flags)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun ASSERT_NE(setns(self->pidfd, 0), 0);
346*4882a593Smuzhiyun EXPECT_EQ(errno, EINVAL);
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun ASSERT_NE(setns(self->pidfd, -1), 0);
349*4882a593Smuzhiyun EXPECT_EQ(errno, EINVAL);
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun ASSERT_NE(setns(self->pidfd, CLONE_VM), 0);
352*4882a593Smuzhiyun EXPECT_EQ(errno, EINVAL);
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun ASSERT_NE(setns(self->pidfd, CLONE_NEWUSER | CLONE_VM), 0);
355*4882a593Smuzhiyun EXPECT_EQ(errno, EINVAL);
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun /* Test that we can't attach to a task that has already exited. */
TEST_F(current_nsset,pidfd_exited_child)359*4882a593Smuzhiyun TEST_F(current_nsset, pidfd_exited_child)
360*4882a593Smuzhiyun {
361*4882a593Smuzhiyun int i;
362*4882a593Smuzhiyun pid_t pid;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun ASSERT_NE(setns(self->child_pidfd_exited, CLONE_NEWUSER | CLONE_NEWNET),
365*4882a593Smuzhiyun 0);
366*4882a593Smuzhiyun EXPECT_EQ(errno, ESRCH);
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun pid = getpid();
369*4882a593Smuzhiyun for (i = 0; i < PIDFD_NS_MAX; i++) {
370*4882a593Smuzhiyun const struct ns_info *info = &ns_info[i];
371*4882a593Smuzhiyun /* Verify that we haven't changed any namespaces. */
372*4882a593Smuzhiyun if (self->nsfds[i] >= 0)
373*4882a593Smuzhiyun ASSERT_EQ(in_same_namespace(self->nsfds[i], pid, info->name), 1);
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
TEST_F(current_nsset,pidfd_incremental_setns)377*4882a593Smuzhiyun TEST_F(current_nsset, pidfd_incremental_setns)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun int i;
380*4882a593Smuzhiyun pid_t pid;
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun pid = getpid();
383*4882a593Smuzhiyun for (i = 0; i < PIDFD_NS_MAX; i++) {
384*4882a593Smuzhiyun const struct ns_info *info = &ns_info[i];
385*4882a593Smuzhiyun int nsfd;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun if (self->child_nsfds1[i] < 0)
388*4882a593Smuzhiyun continue;
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun if (info->flag) {
391*4882a593Smuzhiyun ASSERT_EQ(setns(self->child_pidfd1, info->flag), 0) {
392*4882a593Smuzhiyun TH_LOG("%m - Failed to setns to %s namespace of %d via pidfd %d",
393*4882a593Smuzhiyun info->name, self->child_pid1,
394*4882a593Smuzhiyun self->child_pidfd1);
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun /* Verify that we have changed to the correct namespaces. */
399*4882a593Smuzhiyun if (info->flag == CLONE_NEWPID)
400*4882a593Smuzhiyun nsfd = self->nsfds[i];
401*4882a593Smuzhiyun else
402*4882a593Smuzhiyun nsfd = self->child_nsfds1[i];
403*4882a593Smuzhiyun ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
404*4882a593Smuzhiyun TH_LOG("setns failed to place us correctly into %s namespace of %d via pidfd %d",
405*4882a593Smuzhiyun info->name, self->child_pid1,
406*4882a593Smuzhiyun self->child_pidfd1);
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun TH_LOG("Managed to correctly setns to %s namespace of %d via pidfd %d",
409*4882a593Smuzhiyun info->name, self->child_pid1, self->child_pidfd1);
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun }
412*4882a593Smuzhiyun
TEST_F(current_nsset,nsfd_incremental_setns)413*4882a593Smuzhiyun TEST_F(current_nsset, nsfd_incremental_setns)
414*4882a593Smuzhiyun {
415*4882a593Smuzhiyun int i;
416*4882a593Smuzhiyun pid_t pid;
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun pid = getpid();
419*4882a593Smuzhiyun for (i = 0; i < PIDFD_NS_MAX; i++) {
420*4882a593Smuzhiyun const struct ns_info *info = &ns_info[i];
421*4882a593Smuzhiyun int nsfd;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun if (self->child_nsfds1[i] < 0)
424*4882a593Smuzhiyun continue;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun if (info->flag) {
427*4882a593Smuzhiyun ASSERT_EQ(setns(self->child_nsfds1[i], info->flag), 0) {
428*4882a593Smuzhiyun TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d",
429*4882a593Smuzhiyun info->name, self->child_pid1,
430*4882a593Smuzhiyun self->child_nsfds1[i]);
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun /* Verify that we have changed to the correct namespaces. */
435*4882a593Smuzhiyun if (info->flag == CLONE_NEWPID)
436*4882a593Smuzhiyun nsfd = self->nsfds[i];
437*4882a593Smuzhiyun else
438*4882a593Smuzhiyun nsfd = self->child_nsfds1[i];
439*4882a593Smuzhiyun ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
440*4882a593Smuzhiyun TH_LOG("setns failed to place us correctly into %s namespace of %d via nsfd %d",
441*4882a593Smuzhiyun info->name, self->child_pid1,
442*4882a593Smuzhiyun self->child_nsfds1[i]);
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d",
445*4882a593Smuzhiyun info->name, self->child_pid1, self->child_nsfds1[i]);
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
TEST_F(current_nsset,pidfd_one_shot_setns)449*4882a593Smuzhiyun TEST_F(current_nsset, pidfd_one_shot_setns)
450*4882a593Smuzhiyun {
451*4882a593Smuzhiyun unsigned flags = 0;
452*4882a593Smuzhiyun int i;
453*4882a593Smuzhiyun pid_t pid;
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun for (i = 0; i < PIDFD_NS_MAX; i++) {
456*4882a593Smuzhiyun const struct ns_info *info = &ns_info[i];
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun if (self->child_nsfds1[i] < 0)
459*4882a593Smuzhiyun continue;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun flags |= info->flag;
462*4882a593Smuzhiyun TH_LOG("Adding %s namespace of %d to list of namespaces to attach to",
463*4882a593Smuzhiyun info->name, self->child_pid1);
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun ASSERT_EQ(setns(self->child_pidfd1, flags), 0) {
467*4882a593Smuzhiyun TH_LOG("%m - Failed to setns to namespaces of %d",
468*4882a593Smuzhiyun self->child_pid1);
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun pid = getpid();
472*4882a593Smuzhiyun for (i = 0; i < PIDFD_NS_MAX; i++) {
473*4882a593Smuzhiyun const struct ns_info *info = &ns_info[i];
474*4882a593Smuzhiyun int nsfd;
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun if (self->child_nsfds1[i] < 0)
477*4882a593Smuzhiyun continue;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun /* Verify that we have changed to the correct namespaces. */
480*4882a593Smuzhiyun if (info->flag == CLONE_NEWPID)
481*4882a593Smuzhiyun nsfd = self->nsfds[i];
482*4882a593Smuzhiyun else
483*4882a593Smuzhiyun nsfd = self->child_nsfds1[i];
484*4882a593Smuzhiyun ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
485*4882a593Smuzhiyun TH_LOG("setns failed to place us correctly into %s namespace of %d",
486*4882a593Smuzhiyun info->name, self->child_pid1);
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun TH_LOG("Managed to correctly setns to %s namespace of %d",
489*4882a593Smuzhiyun info->name, self->child_pid1);
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
TEST_F(current_nsset,no_foul_play)493*4882a593Smuzhiyun TEST_F(current_nsset, no_foul_play)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun unsigned flags = 0;
496*4882a593Smuzhiyun int i;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun for (i = 0; i < PIDFD_NS_MAX; i++) {
499*4882a593Smuzhiyun const struct ns_info *info = &ns_info[i];
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun if (self->child_nsfds1[i] < 0)
502*4882a593Smuzhiyun continue;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun flags |= info->flag;
505*4882a593Smuzhiyun if (info->flag) /* No use logging pid_for_children. */
506*4882a593Smuzhiyun TH_LOG("Adding %s namespace of %d to list of namespaces to attach to",
507*4882a593Smuzhiyun info->name, self->child_pid1);
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun ASSERT_EQ(setns(self->child_pidfd1, flags), 0) {
511*4882a593Smuzhiyun TH_LOG("%m - Failed to setns to namespaces of %d vid pidfd %d",
512*4882a593Smuzhiyun self->child_pid1, self->child_pidfd1);
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun /*
516*4882a593Smuzhiyun * Can't setns to a user namespace outside of our hierarchy since we
517*4882a593Smuzhiyun * don't have caps in there and didn't create it. That means that under
518*4882a593Smuzhiyun * no circumstances should we be able to setns to any of the other
519*4882a593Smuzhiyun * ones since they aren't owned by our user namespace.
520*4882a593Smuzhiyun */
521*4882a593Smuzhiyun for (i = 0; i < PIDFD_NS_MAX; i++) {
522*4882a593Smuzhiyun const struct ns_info *info = &ns_info[i];
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun if (self->child_nsfds2[i] < 0 || !info->flag)
525*4882a593Smuzhiyun continue;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun ASSERT_NE(setns(self->child_pidfd2, info->flag), 0) {
528*4882a593Smuzhiyun TH_LOG("Managed to setns to %s namespace of %d via pidfd %d",
529*4882a593Smuzhiyun info->name, self->child_pid2,
530*4882a593Smuzhiyun self->child_pidfd2);
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun TH_LOG("%m - Correctly failed to setns to %s namespace of %d via pidfd %d",
533*4882a593Smuzhiyun info->name, self->child_pid2,
534*4882a593Smuzhiyun self->child_pidfd2);
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun ASSERT_NE(setns(self->child_nsfds2[i], info->flag), 0) {
537*4882a593Smuzhiyun TH_LOG("Managed to setns to %s namespace of %d via nsfd %d",
538*4882a593Smuzhiyun info->name, self->child_pid2,
539*4882a593Smuzhiyun self->child_nsfds2[i]);
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d",
542*4882a593Smuzhiyun info->name, self->child_pid2,
543*4882a593Smuzhiyun self->child_nsfds2[i]);
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun
TEST(setns_einval)547*4882a593Smuzhiyun TEST(setns_einval)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun int fd;
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun fd = sys_memfd_create("rostock", 0);
552*4882a593Smuzhiyun EXPECT_GT(fd, 0);
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun ASSERT_NE(setns(fd, 0), 0);
555*4882a593Smuzhiyun EXPECT_EQ(errno, EINVAL);
556*4882a593Smuzhiyun close(fd);
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun TEST_HARNESS_MAIN
560