1*59a42b0eSChristian Brauner // SPDX-License-Identifier: GPL-2.0
2*59a42b0eSChristian Brauner
3*59a42b0eSChristian Brauner #define _GNU_SOURCE
4*59a42b0eSChristian Brauner #include <errno.h>
5*59a42b0eSChristian Brauner #include <fcntl.h>
6*59a42b0eSChristian Brauner #include <limits.h>
7*59a42b0eSChristian Brauner #include <linux/types.h>
8*59a42b0eSChristian Brauner #include <poll.h>
9*59a42b0eSChristian Brauner #include <sched.h>
10*59a42b0eSChristian Brauner #include <signal.h>
11*59a42b0eSChristian Brauner #include <stdio.h>
12*59a42b0eSChristian Brauner #include <stdlib.h>
13*59a42b0eSChristian Brauner #include <string.h>
14*59a42b0eSChristian Brauner #include <syscall.h>
15*59a42b0eSChristian Brauner #include <sys/prctl.h>
16*59a42b0eSChristian Brauner #include <sys/wait.h>
17*59a42b0eSChristian Brauner #include <unistd.h>
18*59a42b0eSChristian Brauner #include <sys/socket.h>
19*59a42b0eSChristian Brauner #include <linux/kcmp.h>
20*59a42b0eSChristian Brauner #include <sys/stat.h>
21*59a42b0eSChristian Brauner
22*59a42b0eSChristian Brauner #include "pidfd.h"
23*59a42b0eSChristian Brauner #include "../kselftest_harness.h"
24*59a42b0eSChristian Brauner
FIXTURE(file_handle)25*59a42b0eSChristian Brauner FIXTURE(file_handle)
26*59a42b0eSChristian Brauner {
27*59a42b0eSChristian Brauner pid_t pid;
28*59a42b0eSChristian Brauner int pidfd;
29*59a42b0eSChristian Brauner
30*59a42b0eSChristian Brauner pid_t child_pid1;
31*59a42b0eSChristian Brauner int child_pidfd1;
32*59a42b0eSChristian Brauner
33*59a42b0eSChristian Brauner pid_t child_pid2;
34*59a42b0eSChristian Brauner int child_pidfd2;
35*59a42b0eSChristian Brauner
36*59a42b0eSChristian Brauner pid_t child_pid3;
37*59a42b0eSChristian Brauner int child_pidfd3;
38*59a42b0eSChristian Brauner };
39*59a42b0eSChristian Brauner
FIXTURE_SETUP(file_handle)40*59a42b0eSChristian Brauner FIXTURE_SETUP(file_handle)
41*59a42b0eSChristian Brauner {
42*59a42b0eSChristian Brauner int ret;
43*59a42b0eSChristian Brauner int ipc_sockets[2];
44*59a42b0eSChristian Brauner char c;
45*59a42b0eSChristian Brauner
46*59a42b0eSChristian Brauner self->pid = getpid();
47*59a42b0eSChristian Brauner self->pidfd = sys_pidfd_open(self->pid, 0);
48*59a42b0eSChristian Brauner ASSERT_GE(self->pidfd, 0);
49*59a42b0eSChristian Brauner
50*59a42b0eSChristian Brauner ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
51*59a42b0eSChristian Brauner EXPECT_EQ(ret, 0);
52*59a42b0eSChristian Brauner
53*59a42b0eSChristian Brauner self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER);
54*59a42b0eSChristian Brauner EXPECT_GE(self->child_pid1, 0);
55*59a42b0eSChristian Brauner
56*59a42b0eSChristian Brauner if (self->child_pid1 == 0) {
57*59a42b0eSChristian Brauner close(ipc_sockets[0]);
58*59a42b0eSChristian Brauner
59*59a42b0eSChristian Brauner if (write_nointr(ipc_sockets[1], "1", 1) < 0)
60*59a42b0eSChristian Brauner _exit(EXIT_FAILURE);
61*59a42b0eSChristian Brauner
62*59a42b0eSChristian Brauner close(ipc_sockets[1]);
63*59a42b0eSChristian Brauner
64*59a42b0eSChristian Brauner pause();
65*59a42b0eSChristian Brauner _exit(EXIT_SUCCESS);
66*59a42b0eSChristian Brauner }
67*59a42b0eSChristian Brauner
68*59a42b0eSChristian Brauner close(ipc_sockets[1]);
69*59a42b0eSChristian Brauner ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
70*59a42b0eSChristian Brauner close(ipc_sockets[0]);
71*59a42b0eSChristian Brauner
72*59a42b0eSChristian Brauner ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
73*59a42b0eSChristian Brauner EXPECT_EQ(ret, 0);
74*59a42b0eSChristian Brauner
75*59a42b0eSChristian Brauner self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER | CLONE_NEWPID);
76*59a42b0eSChristian Brauner EXPECT_GE(self->child_pid2, 0);
77*59a42b0eSChristian Brauner
78*59a42b0eSChristian Brauner if (self->child_pid2 == 0) {
79*59a42b0eSChristian Brauner close(ipc_sockets[0]);
80*59a42b0eSChristian Brauner
81*59a42b0eSChristian Brauner if (write_nointr(ipc_sockets[1], "1", 1) < 0)
82*59a42b0eSChristian Brauner _exit(EXIT_FAILURE);
83*59a42b0eSChristian Brauner
84*59a42b0eSChristian Brauner close(ipc_sockets[1]);
85*59a42b0eSChristian Brauner
86*59a42b0eSChristian Brauner pause();
87*59a42b0eSChristian Brauner _exit(EXIT_SUCCESS);
88*59a42b0eSChristian Brauner }
89*59a42b0eSChristian Brauner
90*59a42b0eSChristian Brauner close(ipc_sockets[1]);
91*59a42b0eSChristian Brauner ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
92*59a42b0eSChristian Brauner close(ipc_sockets[0]);
93*59a42b0eSChristian Brauner
94*59a42b0eSChristian Brauner ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
95*59a42b0eSChristian Brauner EXPECT_EQ(ret, 0);
96*59a42b0eSChristian Brauner
97*59a42b0eSChristian Brauner self->child_pid3 = create_child(&self->child_pidfd3, CLONE_NEWUSER | CLONE_NEWPID);
98*59a42b0eSChristian Brauner EXPECT_GE(self->child_pid3, 0);
99*59a42b0eSChristian Brauner
100*59a42b0eSChristian Brauner if (self->child_pid3 == 0) {
101*59a42b0eSChristian Brauner close(ipc_sockets[0]);
102*59a42b0eSChristian Brauner
103*59a42b0eSChristian Brauner if (write_nointr(ipc_sockets[1], "1", 1) < 0)
104*59a42b0eSChristian Brauner _exit(EXIT_FAILURE);
105*59a42b0eSChristian Brauner
106*59a42b0eSChristian Brauner close(ipc_sockets[1]);
107*59a42b0eSChristian Brauner
108*59a42b0eSChristian Brauner pause();
109*59a42b0eSChristian Brauner _exit(EXIT_SUCCESS);
110*59a42b0eSChristian Brauner }
111*59a42b0eSChristian Brauner
112*59a42b0eSChristian Brauner close(ipc_sockets[1]);
113*59a42b0eSChristian Brauner ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
114*59a42b0eSChristian Brauner close(ipc_sockets[0]);
115*59a42b0eSChristian Brauner }
116*59a42b0eSChristian Brauner
FIXTURE_TEARDOWN(file_handle)117*59a42b0eSChristian Brauner FIXTURE_TEARDOWN(file_handle)
118*59a42b0eSChristian Brauner {
119*59a42b0eSChristian Brauner EXPECT_EQ(close(self->pidfd), 0);
120*59a42b0eSChristian Brauner
121*59a42b0eSChristian Brauner EXPECT_EQ(sys_pidfd_send_signal(self->child_pidfd1, SIGKILL, NULL, 0), 0);
122*59a42b0eSChristian Brauner if (self->child_pidfd1 >= 0)
123*59a42b0eSChristian Brauner EXPECT_EQ(0, close(self->child_pidfd1));
124*59a42b0eSChristian Brauner
125*59a42b0eSChristian Brauner EXPECT_EQ(sys_waitid(P_PID, self->child_pid1, NULL, WEXITED), 0);
126*59a42b0eSChristian Brauner
127*59a42b0eSChristian Brauner EXPECT_EQ(sys_pidfd_send_signal(self->child_pidfd2, SIGKILL, NULL, 0), 0);
128*59a42b0eSChristian Brauner if (self->child_pidfd2 >= 0)
129*59a42b0eSChristian Brauner EXPECT_EQ(0, close(self->child_pidfd2));
130*59a42b0eSChristian Brauner
131*59a42b0eSChristian Brauner EXPECT_EQ(sys_waitid(P_PID, self->child_pid2, NULL, WEXITED), 0);
132*59a42b0eSChristian Brauner
133*59a42b0eSChristian Brauner if (self->child_pidfd3 >= 0) {
134*59a42b0eSChristian Brauner EXPECT_EQ(sys_pidfd_send_signal(self->child_pidfd3, SIGKILL, NULL, 0), 0);
135*59a42b0eSChristian Brauner EXPECT_EQ(0, close(self->child_pidfd3));
136*59a42b0eSChristian Brauner EXPECT_EQ(sys_waitid(P_PID, self->child_pid3, NULL, WEXITED), 0);
137*59a42b0eSChristian Brauner }
138*59a42b0eSChristian Brauner }
139*59a42b0eSChristian Brauner
140*59a42b0eSChristian Brauner /*
141*59a42b0eSChristian Brauner * Test that we can decode a pidfs file handle in the same pid
142*59a42b0eSChristian Brauner * namespace.
143*59a42b0eSChristian Brauner */
TEST_F(file_handle,file_handle_same_pidns)144*59a42b0eSChristian Brauner TEST_F(file_handle, file_handle_same_pidns)
145*59a42b0eSChristian Brauner {
146*59a42b0eSChristian Brauner int mnt_id;
147*59a42b0eSChristian Brauner struct file_handle *fh;
148*59a42b0eSChristian Brauner int pidfd = -EBADF;
149*59a42b0eSChristian Brauner struct stat st1, st2;
150*59a42b0eSChristian Brauner
151*59a42b0eSChristian Brauner fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
152*59a42b0eSChristian Brauner ASSERT_NE(fh, NULL);
153*59a42b0eSChristian Brauner memset(fh, 0, sizeof(struct file_handle) + MAX_HANDLE_SZ);
154*59a42b0eSChristian Brauner fh->handle_bytes = MAX_HANDLE_SZ;
155*59a42b0eSChristian Brauner
156*59a42b0eSChristian Brauner ASSERT_EQ(name_to_handle_at(self->child_pidfd1, "", fh, &mnt_id, AT_EMPTY_PATH), 0);
157*59a42b0eSChristian Brauner
158*59a42b0eSChristian Brauner ASSERT_EQ(fstat(self->child_pidfd1, &st1), 0);
159*59a42b0eSChristian Brauner
160*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh, 0);
161*59a42b0eSChristian Brauner ASSERT_GE(pidfd, 0);
162*59a42b0eSChristian Brauner
163*59a42b0eSChristian Brauner ASSERT_EQ(fstat(pidfd, &st2), 0);
164*59a42b0eSChristian Brauner ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
165*59a42b0eSChristian Brauner
166*59a42b0eSChristian Brauner ASSERT_EQ(close(pidfd), 0);
167*59a42b0eSChristian Brauner
168*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh, O_CLOEXEC);
169*59a42b0eSChristian Brauner ASSERT_GE(pidfd, 0);
170*59a42b0eSChristian Brauner
171*59a42b0eSChristian Brauner ASSERT_EQ(fstat(pidfd, &st2), 0);
172*59a42b0eSChristian Brauner ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
173*59a42b0eSChristian Brauner
174*59a42b0eSChristian Brauner ASSERT_EQ(close(pidfd), 0);
175*59a42b0eSChristian Brauner
176*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh, O_NONBLOCK);
177*59a42b0eSChristian Brauner ASSERT_GE(pidfd, 0);
178*59a42b0eSChristian Brauner
179*59a42b0eSChristian Brauner ASSERT_EQ(fstat(pidfd, &st2), 0);
180*59a42b0eSChristian Brauner ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
181*59a42b0eSChristian Brauner
182*59a42b0eSChristian Brauner ASSERT_EQ(close(pidfd), 0);
183*59a42b0eSChristian Brauner
184*59a42b0eSChristian Brauner free(fh);
185*59a42b0eSChristian Brauner }
186*59a42b0eSChristian Brauner
187*59a42b0eSChristian Brauner /*
188*59a42b0eSChristian Brauner * Test that we can decode a pidfs file handle from a child pid
189*59a42b0eSChristian Brauner * namespace.
190*59a42b0eSChristian Brauner */
TEST_F(file_handle,file_handle_child_pidns)191*59a42b0eSChristian Brauner TEST_F(file_handle, file_handle_child_pidns)
192*59a42b0eSChristian Brauner {
193*59a42b0eSChristian Brauner int mnt_id;
194*59a42b0eSChristian Brauner struct file_handle *fh;
195*59a42b0eSChristian Brauner int pidfd = -EBADF;
196*59a42b0eSChristian Brauner struct stat st1, st2;
197*59a42b0eSChristian Brauner
198*59a42b0eSChristian Brauner fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
199*59a42b0eSChristian Brauner ASSERT_NE(fh, NULL);
200*59a42b0eSChristian Brauner memset(fh, 0, sizeof(struct file_handle) + MAX_HANDLE_SZ);
201*59a42b0eSChristian Brauner fh->handle_bytes = MAX_HANDLE_SZ;
202*59a42b0eSChristian Brauner
203*59a42b0eSChristian Brauner ASSERT_EQ(name_to_handle_at(self->child_pidfd2, "", fh, &mnt_id, AT_EMPTY_PATH), 0);
204*59a42b0eSChristian Brauner
205*59a42b0eSChristian Brauner ASSERT_EQ(fstat(self->child_pidfd2, &st1), 0);
206*59a42b0eSChristian Brauner
207*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh, 0);
208*59a42b0eSChristian Brauner ASSERT_GE(pidfd, 0);
209*59a42b0eSChristian Brauner
210*59a42b0eSChristian Brauner ASSERT_EQ(fstat(pidfd, &st2), 0);
211*59a42b0eSChristian Brauner ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
212*59a42b0eSChristian Brauner
213*59a42b0eSChristian Brauner ASSERT_EQ(close(pidfd), 0);
214*59a42b0eSChristian Brauner
215*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh, O_CLOEXEC);
216*59a42b0eSChristian Brauner ASSERT_GE(pidfd, 0);
217*59a42b0eSChristian Brauner
218*59a42b0eSChristian Brauner ASSERT_EQ(fstat(pidfd, &st2), 0);
219*59a42b0eSChristian Brauner ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
220*59a42b0eSChristian Brauner
221*59a42b0eSChristian Brauner ASSERT_EQ(close(pidfd), 0);
222*59a42b0eSChristian Brauner
223*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh, O_NONBLOCK);
224*59a42b0eSChristian Brauner ASSERT_GE(pidfd, 0);
225*59a42b0eSChristian Brauner
226*59a42b0eSChristian Brauner ASSERT_EQ(fstat(pidfd, &st2), 0);
227*59a42b0eSChristian Brauner ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
228*59a42b0eSChristian Brauner
229*59a42b0eSChristian Brauner ASSERT_EQ(close(pidfd), 0);
230*59a42b0eSChristian Brauner
231*59a42b0eSChristian Brauner free(fh);
232*59a42b0eSChristian Brauner }
233*59a42b0eSChristian Brauner
234*59a42b0eSChristian Brauner /*
235*59a42b0eSChristian Brauner * Test that we fail to decode a pidfs file handle from an ancestor
236*59a42b0eSChristian Brauner * child pid namespace.
237*59a42b0eSChristian Brauner */
TEST_F(file_handle,file_handle_foreign_pidns)238*59a42b0eSChristian Brauner TEST_F(file_handle, file_handle_foreign_pidns)
239*59a42b0eSChristian Brauner {
240*59a42b0eSChristian Brauner int mnt_id;
241*59a42b0eSChristian Brauner struct file_handle *fh;
242*59a42b0eSChristian Brauner pid_t pid;
243*59a42b0eSChristian Brauner
244*59a42b0eSChristian Brauner fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
245*59a42b0eSChristian Brauner ASSERT_NE(fh, NULL);
246*59a42b0eSChristian Brauner memset(fh, 0, sizeof(struct file_handle) + MAX_HANDLE_SZ);
247*59a42b0eSChristian Brauner fh->handle_bytes = MAX_HANDLE_SZ;
248*59a42b0eSChristian Brauner
249*59a42b0eSChristian Brauner ASSERT_EQ(name_to_handle_at(self->pidfd, "", fh, &mnt_id, AT_EMPTY_PATH), 0);
250*59a42b0eSChristian Brauner
251*59a42b0eSChristian Brauner ASSERT_EQ(setns(self->child_pidfd2, CLONE_NEWUSER | CLONE_NEWPID), 0);
252*59a42b0eSChristian Brauner
253*59a42b0eSChristian Brauner pid = fork();
254*59a42b0eSChristian Brauner ASSERT_GE(pid, 0);
255*59a42b0eSChristian Brauner
256*59a42b0eSChristian Brauner if (pid == 0) {
257*59a42b0eSChristian Brauner int pidfd = open_by_handle_at(self->pidfd, fh, 0);
258*59a42b0eSChristian Brauner if (pidfd >= 0) {
259*59a42b0eSChristian Brauner TH_LOG("Managed to open pidfd outside of the caller's pid namespace hierarchy");
260*59a42b0eSChristian Brauner _exit(1);
261*59a42b0eSChristian Brauner }
262*59a42b0eSChristian Brauner _exit(0);
263*59a42b0eSChristian Brauner }
264*59a42b0eSChristian Brauner
265*59a42b0eSChristian Brauner ASSERT_EQ(wait_for_pid(pid), 0);
266*59a42b0eSChristian Brauner
267*59a42b0eSChristian Brauner free(fh);
268*59a42b0eSChristian Brauner }
269*59a42b0eSChristian Brauner
270*59a42b0eSChristian Brauner /*
271*59a42b0eSChristian Brauner * Test that we can decode a pidfs file handle of a process that has
272*59a42b0eSChristian Brauner * exited but not been reaped.
273*59a42b0eSChristian Brauner */
TEST_F(file_handle,pid_has_exited)274*59a42b0eSChristian Brauner TEST_F(file_handle, pid_has_exited)
275*59a42b0eSChristian Brauner {
276*59a42b0eSChristian Brauner int mnt_id, pidfd, child_pidfd3;
277*59a42b0eSChristian Brauner struct file_handle *fh;
278*59a42b0eSChristian Brauner struct stat st1, st2;
279*59a42b0eSChristian Brauner
280*59a42b0eSChristian Brauner fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
281*59a42b0eSChristian Brauner ASSERT_NE(fh, NULL);
282*59a42b0eSChristian Brauner memset(fh, 0, sizeof(struct file_handle) + MAX_HANDLE_SZ);
283*59a42b0eSChristian Brauner fh->handle_bytes = MAX_HANDLE_SZ;
284*59a42b0eSChristian Brauner
285*59a42b0eSChristian Brauner ASSERT_EQ(name_to_handle_at(self->child_pidfd3, "", fh, &mnt_id, AT_EMPTY_PATH), 0);
286*59a42b0eSChristian Brauner
287*59a42b0eSChristian Brauner ASSERT_EQ(fstat(self->child_pidfd3, &st1), 0);
288*59a42b0eSChristian Brauner
289*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh, 0);
290*59a42b0eSChristian Brauner ASSERT_GE(pidfd, 0);
291*59a42b0eSChristian Brauner
292*59a42b0eSChristian Brauner ASSERT_EQ(fstat(pidfd, &st2), 0);
293*59a42b0eSChristian Brauner ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
294*59a42b0eSChristian Brauner
295*59a42b0eSChristian Brauner ASSERT_EQ(close(pidfd), 0);
296*59a42b0eSChristian Brauner
297*59a42b0eSChristian Brauner child_pidfd3 = self->child_pidfd3;
298*59a42b0eSChristian Brauner self->child_pidfd3 = -EBADF;
299*59a42b0eSChristian Brauner EXPECT_EQ(sys_pidfd_send_signal(child_pidfd3, SIGKILL, NULL, 0), 0);
300*59a42b0eSChristian Brauner EXPECT_EQ(close(child_pidfd3), 0);
301*59a42b0eSChristian Brauner EXPECT_EQ(sys_waitid(P_PID, self->child_pid3, NULL, WEXITED | WNOWAIT), 0);
302*59a42b0eSChristian Brauner
303*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh, 0);
304*59a42b0eSChristian Brauner ASSERT_GE(pidfd, 0);
305*59a42b0eSChristian Brauner
306*59a42b0eSChristian Brauner EXPECT_EQ(sys_waitid(P_PID, self->child_pid3, NULL, WEXITED), 0);
307*59a42b0eSChristian Brauner }
308*59a42b0eSChristian Brauner
309*59a42b0eSChristian Brauner /*
310*59a42b0eSChristian Brauner * Test that we fail to decode a pidfs file handle of a process that has
311*59a42b0eSChristian Brauner * already been reaped.
312*59a42b0eSChristian Brauner */
TEST_F(file_handle,pid_has_been_reaped)313*59a42b0eSChristian Brauner TEST_F(file_handle, pid_has_been_reaped)
314*59a42b0eSChristian Brauner {
315*59a42b0eSChristian Brauner int mnt_id, pidfd, child_pidfd3;
316*59a42b0eSChristian Brauner struct file_handle *fh;
317*59a42b0eSChristian Brauner struct stat st1, st2;
318*59a42b0eSChristian Brauner
319*59a42b0eSChristian Brauner fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
320*59a42b0eSChristian Brauner ASSERT_NE(fh, NULL);
321*59a42b0eSChristian Brauner memset(fh, 0, sizeof(struct file_handle) + MAX_HANDLE_SZ);
322*59a42b0eSChristian Brauner fh->handle_bytes = MAX_HANDLE_SZ;
323*59a42b0eSChristian Brauner
324*59a42b0eSChristian Brauner ASSERT_EQ(name_to_handle_at(self->child_pidfd3, "", fh, &mnt_id, AT_EMPTY_PATH), 0);
325*59a42b0eSChristian Brauner
326*59a42b0eSChristian Brauner ASSERT_EQ(fstat(self->child_pidfd3, &st1), 0);
327*59a42b0eSChristian Brauner
328*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh, 0);
329*59a42b0eSChristian Brauner ASSERT_GE(pidfd, 0);
330*59a42b0eSChristian Brauner
331*59a42b0eSChristian Brauner ASSERT_EQ(fstat(pidfd, &st2), 0);
332*59a42b0eSChristian Brauner ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
333*59a42b0eSChristian Brauner
334*59a42b0eSChristian Brauner ASSERT_EQ(close(pidfd), 0);
335*59a42b0eSChristian Brauner
336*59a42b0eSChristian Brauner child_pidfd3 = self->child_pidfd3;
337*59a42b0eSChristian Brauner self->child_pidfd3 = -EBADF;
338*59a42b0eSChristian Brauner EXPECT_EQ(sys_pidfd_send_signal(child_pidfd3, SIGKILL, NULL, 0), 0);
339*59a42b0eSChristian Brauner EXPECT_EQ(close(child_pidfd3), 0);
340*59a42b0eSChristian Brauner EXPECT_EQ(sys_waitid(P_PID, self->child_pid3, NULL, WEXITED), 0);
341*59a42b0eSChristian Brauner
342*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh, 0);
343*59a42b0eSChristian Brauner ASSERT_LT(pidfd, 0);
344*59a42b0eSChristian Brauner }
345*59a42b0eSChristian Brauner
346*59a42b0eSChristian Brauner /*
347*59a42b0eSChristian Brauner * Test valid flags to open a pidfd file handle. Note, that
348*59a42b0eSChristian Brauner * PIDFD_NONBLOCK is defined as O_NONBLOCK and O_NONBLOCK is an alias to
349*59a42b0eSChristian Brauner * O_NDELAY. Also note that PIDFD_THREAD is an alias for O_EXCL.
350*59a42b0eSChristian Brauner */
TEST_F(file_handle,open_by_handle_at_valid_flags)351*59a42b0eSChristian Brauner TEST_F(file_handle, open_by_handle_at_valid_flags)
352*59a42b0eSChristian Brauner {
353*59a42b0eSChristian Brauner int mnt_id;
354*59a42b0eSChristian Brauner struct file_handle *fh;
355*59a42b0eSChristian Brauner int pidfd = -EBADF;
356*59a42b0eSChristian Brauner struct stat st1, st2;
357*59a42b0eSChristian Brauner
358*59a42b0eSChristian Brauner fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
359*59a42b0eSChristian Brauner ASSERT_NE(fh, NULL);
360*59a42b0eSChristian Brauner memset(fh, 0, sizeof(struct file_handle) + MAX_HANDLE_SZ);
361*59a42b0eSChristian Brauner fh->handle_bytes = MAX_HANDLE_SZ;
362*59a42b0eSChristian Brauner
363*59a42b0eSChristian Brauner ASSERT_EQ(name_to_handle_at(self->child_pidfd2, "", fh, &mnt_id, AT_EMPTY_PATH), 0);
364*59a42b0eSChristian Brauner
365*59a42b0eSChristian Brauner ASSERT_EQ(fstat(self->child_pidfd2, &st1), 0);
366*59a42b0eSChristian Brauner
367*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh,
368*59a42b0eSChristian Brauner O_RDONLY |
369*59a42b0eSChristian Brauner O_WRONLY |
370*59a42b0eSChristian Brauner O_RDWR |
371*59a42b0eSChristian Brauner O_NONBLOCK |
372*59a42b0eSChristian Brauner O_NDELAY |
373*59a42b0eSChristian Brauner O_CLOEXEC |
374*59a42b0eSChristian Brauner O_EXCL);
375*59a42b0eSChristian Brauner ASSERT_GE(pidfd, 0);
376*59a42b0eSChristian Brauner
377*59a42b0eSChristian Brauner ASSERT_EQ(fstat(pidfd, &st2), 0);
378*59a42b0eSChristian Brauner ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
379*59a42b0eSChristian Brauner
380*59a42b0eSChristian Brauner ASSERT_EQ(close(pidfd), 0);
381*59a42b0eSChristian Brauner }
382*59a42b0eSChristian Brauner
383*59a42b0eSChristian Brauner /*
384*59a42b0eSChristian Brauner * Test that invalid flags passed to open a pidfd file handle are
385*59a42b0eSChristian Brauner * rejected.
386*59a42b0eSChristian Brauner */
TEST_F(file_handle,open_by_handle_at_invalid_flags)387*59a42b0eSChristian Brauner TEST_F(file_handle, open_by_handle_at_invalid_flags)
388*59a42b0eSChristian Brauner {
389*59a42b0eSChristian Brauner int mnt_id;
390*59a42b0eSChristian Brauner struct file_handle *fh;
391*59a42b0eSChristian Brauner int pidfd = -EBADF;
392*59a42b0eSChristian Brauner static const struct invalid_pidfs_file_handle_flags {
393*59a42b0eSChristian Brauner int oflag;
394*59a42b0eSChristian Brauner const char *oflag_name;
395*59a42b0eSChristian Brauner } invalid_pidfs_file_handle_flags[] = {
396*59a42b0eSChristian Brauner { FASYNC, "FASYNC" },
397*59a42b0eSChristian Brauner { O_CREAT, "O_CREAT" },
398*59a42b0eSChristian Brauner { O_NOCTTY, "O_NOCTTY" },
399*59a42b0eSChristian Brauner { O_CREAT, "O_CREAT" },
400*59a42b0eSChristian Brauner { O_TRUNC, "O_TRUNC" },
401*59a42b0eSChristian Brauner { O_APPEND, "O_APPEND" },
402*59a42b0eSChristian Brauner { O_SYNC, "O_SYNC" },
403*59a42b0eSChristian Brauner { O_DSYNC, "O_DSYNC" },
404*59a42b0eSChristian Brauner { O_DIRECT, "O_DIRECT" },
405*59a42b0eSChristian Brauner { O_DIRECTORY, "O_DIRECTORY" },
406*59a42b0eSChristian Brauner { O_NOFOLLOW, "O_NOFOLLOW" },
407*59a42b0eSChristian Brauner { O_NOATIME, "O_NOATIME" },
408*59a42b0eSChristian Brauner { O_PATH, "O_PATH" },
409*59a42b0eSChristian Brauner { O_TMPFILE, "O_TMPFILE" },
410*59a42b0eSChristian Brauner /*
411*59a42b0eSChristian Brauner * O_LARGEFILE is added implicitly by
412*59a42b0eSChristian Brauner * open_by_handle_at() so pidfs simply masks it off.
413*59a42b0eSChristian Brauner */
414*59a42b0eSChristian Brauner };
415*59a42b0eSChristian Brauner
416*59a42b0eSChristian Brauner fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
417*59a42b0eSChristian Brauner ASSERT_NE(fh, NULL);
418*59a42b0eSChristian Brauner memset(fh, 0, sizeof(struct file_handle) + MAX_HANDLE_SZ);
419*59a42b0eSChristian Brauner fh->handle_bytes = MAX_HANDLE_SZ;
420*59a42b0eSChristian Brauner
421*59a42b0eSChristian Brauner ASSERT_EQ(name_to_handle_at(self->child_pidfd2, "", fh, &mnt_id, AT_EMPTY_PATH), 0);
422*59a42b0eSChristian Brauner
423*59a42b0eSChristian Brauner for (int i = 0; i < ARRAY_SIZE(invalid_pidfs_file_handle_flags); i++) {
424*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh, invalid_pidfs_file_handle_flags[i].oflag);
425*59a42b0eSChristian Brauner ASSERT_LT(pidfd, 0) {
426*59a42b0eSChristian Brauner TH_LOG("open_by_handle_at() succeeded with invalid flags: %s", invalid_pidfs_file_handle_flags[i].oflag_name);
427*59a42b0eSChristian Brauner }
428*59a42b0eSChristian Brauner }
429*59a42b0eSChristian Brauner }
430*59a42b0eSChristian Brauner
431*59a42b0eSChristian Brauner /* Test that lookup fails. */
TEST_F(file_handle,lookup_must_fail)432*59a42b0eSChristian Brauner TEST_F(file_handle, lookup_must_fail)
433*59a42b0eSChristian Brauner {
434*59a42b0eSChristian Brauner int mnt_id;
435*59a42b0eSChristian Brauner struct file_handle *fh;
436*59a42b0eSChristian Brauner
437*59a42b0eSChristian Brauner fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
438*59a42b0eSChristian Brauner ASSERT_NE(fh, NULL);
439*59a42b0eSChristian Brauner memset(fh, 0, sizeof(struct file_handle) + MAX_HANDLE_SZ);
440*59a42b0eSChristian Brauner fh->handle_bytes = MAX_HANDLE_SZ;
441*59a42b0eSChristian Brauner
442*59a42b0eSChristian Brauner ASSERT_NE(name_to_handle_at(self->child_pidfd2, "lookup-is-not-possible-with-pidfs", fh, &mnt_id, AT_EMPTY_PATH), 0);
443*59a42b0eSChristian Brauner ASSERT_EQ(errno, ENOTDIR);
444*59a42b0eSChristian Brauner ASSERT_NE(name_to_handle_at(self->child_pidfd2, "lookup-is-not-possible-with-pidfs", fh, &mnt_id, 0), 0);
445*59a42b0eSChristian Brauner ASSERT_EQ(errno, ENOTDIR);
446*59a42b0eSChristian Brauner }
447*59a42b0eSChristian Brauner
448*59a42b0eSChristian Brauner #ifndef AT_HANDLE_CONNECTABLE
449*59a42b0eSChristian Brauner #define AT_HANDLE_CONNECTABLE 0x002
450*59a42b0eSChristian Brauner #endif
451*59a42b0eSChristian Brauner
452*59a42b0eSChristian Brauner /*
453*59a42b0eSChristian Brauner * Test that AT_HANDLE_CONNECTABLE is rejected. Connectable file handles
454*59a42b0eSChristian Brauner * don't make sense for pidfs. Note that currently AT_HANDLE_CONNECTABLE
455*59a42b0eSChristian Brauner * is rejected because it is incompatible with AT_EMPTY_PATH which is
456*59a42b0eSChristian Brauner * required with pidfds as we don't support lookup.
457*59a42b0eSChristian Brauner */
TEST_F(file_handle,invalid_name_to_handle_at_flags)458*59a42b0eSChristian Brauner TEST_F(file_handle, invalid_name_to_handle_at_flags)
459*59a42b0eSChristian Brauner {
460*59a42b0eSChristian Brauner int mnt_id;
461*59a42b0eSChristian Brauner struct file_handle *fh;
462*59a42b0eSChristian Brauner
463*59a42b0eSChristian Brauner fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
464*59a42b0eSChristian Brauner ASSERT_NE(fh, NULL);
465*59a42b0eSChristian Brauner memset(fh, 0, sizeof(struct file_handle) + MAX_HANDLE_SZ);
466*59a42b0eSChristian Brauner fh->handle_bytes = MAX_HANDLE_SZ;
467*59a42b0eSChristian Brauner
468*59a42b0eSChristian Brauner ASSERT_NE(name_to_handle_at(self->child_pidfd2, "", fh, &mnt_id, AT_EMPTY_PATH | AT_HANDLE_CONNECTABLE), 0);
469*59a42b0eSChristian Brauner }
470*59a42b0eSChristian Brauner
471*59a42b0eSChristian Brauner #ifndef AT_HANDLE_FID
472*59a42b0eSChristian Brauner #define AT_HANDLE_FID 0x200
473*59a42b0eSChristian Brauner #endif
474*59a42b0eSChristian Brauner
475*59a42b0eSChristian Brauner /*
476*59a42b0eSChristian Brauner * Test that a request with AT_HANDLE_FID always leads to decodable file
477*59a42b0eSChristian Brauner * handle as pidfs always provides export operations.
478*59a42b0eSChristian Brauner */
TEST_F(file_handle,valid_name_to_handle_at_flags)479*59a42b0eSChristian Brauner TEST_F(file_handle, valid_name_to_handle_at_flags)
480*59a42b0eSChristian Brauner {
481*59a42b0eSChristian Brauner int mnt_id, pidfd;
482*59a42b0eSChristian Brauner struct file_handle *fh;
483*59a42b0eSChristian Brauner struct stat st1, st2;
484*59a42b0eSChristian Brauner
485*59a42b0eSChristian Brauner fh = malloc(sizeof(struct file_handle) + MAX_HANDLE_SZ);
486*59a42b0eSChristian Brauner ASSERT_NE(fh, NULL);
487*59a42b0eSChristian Brauner memset(fh, 0, sizeof(struct file_handle) + MAX_HANDLE_SZ);
488*59a42b0eSChristian Brauner fh->handle_bytes = MAX_HANDLE_SZ;
489*59a42b0eSChristian Brauner
490*59a42b0eSChristian Brauner ASSERT_EQ(name_to_handle_at(self->child_pidfd2, "", fh, &mnt_id, AT_EMPTY_PATH | AT_HANDLE_FID), 0);
491*59a42b0eSChristian Brauner
492*59a42b0eSChristian Brauner ASSERT_EQ(fstat(self->child_pidfd2, &st1), 0);
493*59a42b0eSChristian Brauner
494*59a42b0eSChristian Brauner pidfd = open_by_handle_at(self->pidfd, fh, 0);
495*59a42b0eSChristian Brauner ASSERT_GE(pidfd, 0);
496*59a42b0eSChristian Brauner
497*59a42b0eSChristian Brauner ASSERT_EQ(fstat(pidfd, &st2), 0);
498*59a42b0eSChristian Brauner ASSERT_TRUE(st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
499*59a42b0eSChristian Brauner
500*59a42b0eSChristian Brauner ASSERT_EQ(close(pidfd), 0);
501*59a42b0eSChristian Brauner }
502*59a42b0eSChristian Brauner
503*59a42b0eSChristian Brauner TEST_HARNESS_MAIN
504