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 <poll.h>
9 #include <pthread.h>
10 #include <sched.h>
11 #include <signal.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <syscall.h>
16 #include <sys/prctl.h>
17 #include <sys/wait.h>
18 #include <unistd.h>
19 #include <sys/socket.h>
20 #include <linux/kcmp.h>
21 #include <sys/stat.h>
22
23 #include "pidfd.h"
24 #include "../kselftest_harness.h"
25
FIXTURE(pidfd_info)26 FIXTURE(pidfd_info)
27 {
28 pid_t child_pid1;
29 int child_pidfd1;
30
31 pid_t child_pid2;
32 int child_pidfd2;
33
34 pid_t child_pid3;
35 int child_pidfd3;
36
37 pid_t child_pid4;
38 int child_pidfd4;
39 };
40
FIXTURE_SETUP(pidfd_info)41 FIXTURE_SETUP(pidfd_info)
42 {
43 int ret;
44 int ipc_sockets[2];
45 char c;
46
47 ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
48 EXPECT_EQ(ret, 0);
49
50 self->child_pid1 = create_child(&self->child_pidfd1, 0);
51 EXPECT_GE(self->child_pid1, 0);
52
53 if (self->child_pid1 == 0) {
54 close(ipc_sockets[0]);
55
56 if (write_nointr(ipc_sockets[1], "1", 1) < 0)
57 _exit(EXIT_FAILURE);
58
59 close(ipc_sockets[1]);
60
61 pause();
62 _exit(EXIT_SUCCESS);
63 }
64
65 EXPECT_EQ(close(ipc_sockets[1]), 0);
66 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
67 EXPECT_EQ(close(ipc_sockets[0]), 0);
68
69 /* SIGKILL but don't reap. */
70 EXPECT_EQ(sys_pidfd_send_signal(self->child_pidfd1, SIGKILL, NULL, 0), 0);
71
72 ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
73 EXPECT_EQ(ret, 0);
74
75 self->child_pid2 = create_child(&self->child_pidfd2, 0);
76 EXPECT_GE(self->child_pid2, 0);
77
78 if (self->child_pid2 == 0) {
79 close(ipc_sockets[0]);
80
81 if (write_nointr(ipc_sockets[1], "1", 1) < 0)
82 _exit(EXIT_FAILURE);
83
84 close(ipc_sockets[1]);
85
86 pause();
87 _exit(EXIT_SUCCESS);
88 }
89
90 EXPECT_EQ(close(ipc_sockets[1]), 0);
91 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
92 EXPECT_EQ(close(ipc_sockets[0]), 0);
93
94 /* SIGKILL and reap. */
95 EXPECT_EQ(sys_pidfd_send_signal(self->child_pidfd2, SIGKILL, NULL, 0), 0);
96 EXPECT_EQ(sys_waitid(P_PID, self->child_pid2, NULL, WEXITED), 0);
97
98 self->child_pid3 = create_child(&self->child_pidfd3, CLONE_NEWUSER | CLONE_NEWPID);
99 EXPECT_GE(self->child_pid3, 0);
100
101 if (self->child_pid3 == 0)
102 _exit(EXIT_SUCCESS);
103
104 self->child_pid4 = create_child(&self->child_pidfd4, CLONE_NEWUSER | CLONE_NEWPID);
105 EXPECT_GE(self->child_pid4, 0);
106
107 if (self->child_pid4 == 0)
108 _exit(EXIT_SUCCESS);
109
110 EXPECT_EQ(sys_waitid(P_PID, self->child_pid4, NULL, WEXITED), 0);
111 }
112
FIXTURE_TEARDOWN(pidfd_info)113 FIXTURE_TEARDOWN(pidfd_info)
114 {
115 sys_pidfd_send_signal(self->child_pidfd1, SIGKILL, NULL, 0);
116 if (self->child_pidfd1 >= 0)
117 EXPECT_EQ(0, close(self->child_pidfd1));
118
119 sys_waitid(P_PID, self->child_pid1, NULL, WEXITED);
120
121 sys_pidfd_send_signal(self->child_pidfd2, SIGKILL, NULL, 0);
122 if (self->child_pidfd2 >= 0)
123 EXPECT_EQ(0, close(self->child_pidfd2));
124
125 sys_waitid(P_PID, self->child_pid2, NULL, WEXITED);
126 sys_waitid(P_PID, self->child_pid3, NULL, WEXITED);
127 sys_waitid(P_PID, self->child_pid4, NULL, WEXITED);
128 }
129
TEST_F(pidfd_info,sigkill_exit)130 TEST_F(pidfd_info, sigkill_exit)
131 {
132 struct pidfd_info info = {
133 .mask = PIDFD_INFO_CGROUPID,
134 };
135
136 /* Process has exited but not been reaped so this must work. */
137 ASSERT_EQ(ioctl(self->child_pidfd1, PIDFD_GET_INFO, &info), 0);
138
139 info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
140 ASSERT_EQ(ioctl(self->child_pidfd1, PIDFD_GET_INFO, &info), 0);
141 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_CREDS));
142 /* Process has exited but not been reaped, so no PIDFD_INFO_EXIT information yet. */
143 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_EXIT));
144 }
145
TEST_F(pidfd_info,sigkill_reaped)146 TEST_F(pidfd_info, sigkill_reaped)
147 {
148 struct pidfd_info info = {
149 .mask = PIDFD_INFO_CGROUPID,
150 };
151
152 /* Process has already been reaped and PIDFD_INFO_EXIT hasn't been set. */
153 ASSERT_NE(ioctl(self->child_pidfd2, PIDFD_GET_INFO, &info), 0);
154 ASSERT_EQ(errno, ESRCH);
155
156 info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
157 ASSERT_EQ(ioctl(self->child_pidfd2, PIDFD_GET_INFO, &info), 0);
158 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_CREDS));
159 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_EXIT));
160 ASSERT_TRUE(WIFSIGNALED(info.exit_code));
161 ASSERT_EQ(WTERMSIG(info.exit_code), SIGKILL);
162 }
163
TEST_F(pidfd_info,success_exit)164 TEST_F(pidfd_info, success_exit)
165 {
166 struct pidfd_info info = {
167 .mask = PIDFD_INFO_CGROUPID,
168 };
169
170 /* Process has exited but not been reaped so this must work. */
171 ASSERT_EQ(ioctl(self->child_pidfd3, PIDFD_GET_INFO, &info), 0);
172
173 info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
174 ASSERT_EQ(ioctl(self->child_pidfd3, PIDFD_GET_INFO, &info), 0);
175 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_CREDS));
176 /* Process has exited but not been reaped, so no PIDFD_INFO_EXIT information yet. */
177 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_EXIT));
178 }
179
TEST_F(pidfd_info,success_reaped)180 TEST_F(pidfd_info, success_reaped)
181 {
182 struct pidfd_info info = {
183 .mask = PIDFD_INFO_CGROUPID,
184 };
185
186 /* Process has already been reaped and PIDFD_INFO_EXIT hasn't been set. */
187 ASSERT_NE(ioctl(self->child_pidfd4, PIDFD_GET_INFO, &info), 0);
188 ASSERT_EQ(errno, ESRCH);
189
190 info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
191 ASSERT_EQ(ioctl(self->child_pidfd4, PIDFD_GET_INFO, &info), 0);
192 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_CREDS));
193 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_EXIT));
194 ASSERT_TRUE(WIFEXITED(info.exit_code));
195 ASSERT_EQ(WEXITSTATUS(info.exit_code), 0);
196 }
197
TEST_F(pidfd_info,success_reaped_poll)198 TEST_F(pidfd_info, success_reaped_poll)
199 {
200 struct pidfd_info info = {
201 .mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT,
202 };
203 struct pollfd fds = {};
204 int nevents;
205
206 fds.events = POLLIN;
207 fds.fd = self->child_pidfd2;
208
209 nevents = poll(&fds, 1, -1);
210 ASSERT_EQ(nevents, 1);
211 ASSERT_TRUE(!!(fds.revents & POLLIN));
212 ASSERT_TRUE(!!(fds.revents & POLLHUP));
213
214 ASSERT_EQ(ioctl(self->child_pidfd2, PIDFD_GET_INFO, &info), 0);
215 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_CREDS));
216 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_EXIT));
217 ASSERT_TRUE(WIFSIGNALED(info.exit_code));
218 ASSERT_EQ(WTERMSIG(info.exit_code), SIGKILL);
219 }
220
pidfd_info_pause_thread(void * arg)221 static void *pidfd_info_pause_thread(void *arg)
222 {
223 pid_t pid_thread = gettid();
224 int ipc_socket = *(int *)arg;
225
226 /* Inform the grand-parent what the tid of this thread is. */
227 if (write_nointr(ipc_socket, &pid_thread, sizeof(pid_thread)) != sizeof(pid_thread))
228 return NULL;
229
230 close(ipc_socket);
231
232 /* Sleep untill we're killed. */
233 pause();
234 return NULL;
235 }
236
TEST_F(pidfd_info,thread_group)237 TEST_F(pidfd_info, thread_group)
238 {
239 pid_t pid_leader, pid_poller, pid_thread;
240 pthread_t thread;
241 int nevents, pidfd_leader, pidfd_thread, pidfd_leader_thread, ret;
242 int ipc_sockets[2];
243 struct pollfd fds = {};
244 struct pidfd_info info = {
245 .mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT,
246 }, info2;
247
248 ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
249 EXPECT_EQ(ret, 0);
250
251 pid_leader = create_child(&pidfd_leader, 0);
252 EXPECT_GE(pid_leader, 0);
253
254 if (pid_leader == 0) {
255 close(ipc_sockets[0]);
256
257 /* The thread will outlive the thread-group leader. */
258 if (pthread_create(&thread, NULL, pidfd_info_pause_thread, &ipc_sockets[1]))
259 syscall(__NR_exit, EXIT_FAILURE);
260
261 /* Make the thread-group leader exit prematurely. */
262 syscall(__NR_exit, EXIT_SUCCESS);
263 }
264
265 /*
266 * Opening a PIDFD_THREAD aka thread-specific pidfd based on a
267 * thread-group leader must succeed.
268 */
269 pidfd_leader_thread = sys_pidfd_open(pid_leader, PIDFD_THREAD);
270 ASSERT_GE(pidfd_leader_thread, 0);
271
272 pid_poller = fork();
273 ASSERT_GE(pid_poller, 0);
274 if (pid_poller == 0) {
275 /*
276 * We can't poll and wait for the old thread-group
277 * leader to exit using a thread-specific pidfd. The
278 * thread-group leader exited prematurely and
279 * notification is delayed until all subthreads have
280 * exited.
281 */
282 fds.events = POLLIN;
283 fds.fd = pidfd_leader_thread;
284 nevents = poll(&fds, 1, 10000 /* wait 5 seconds */);
285 if (nevents != 0)
286 _exit(EXIT_FAILURE);
287 if (fds.revents & POLLIN)
288 _exit(EXIT_FAILURE);
289 if (fds.revents & POLLHUP)
290 _exit(EXIT_FAILURE);
291 _exit(EXIT_SUCCESS);
292 }
293
294 /* Retrieve the tid of the thread. */
295 EXPECT_EQ(close(ipc_sockets[1]), 0);
296 ASSERT_EQ(read_nointr(ipc_sockets[0], &pid_thread, sizeof(pid_thread)), sizeof(pid_thread));
297 EXPECT_EQ(close(ipc_sockets[0]), 0);
298
299 /* Opening a thread as a thread-group leader must fail. */
300 pidfd_thread = sys_pidfd_open(pid_thread, 0);
301 ASSERT_LT(pidfd_thread, 0);
302 ASSERT_EQ(errno, ENOENT);
303
304 /* Opening a thread as a PIDFD_THREAD must succeed. */
305 pidfd_thread = sys_pidfd_open(pid_thread, PIDFD_THREAD);
306 ASSERT_GE(pidfd_thread, 0);
307
308 ASSERT_EQ(wait_for_pid(pid_poller), 0);
309
310 /*
311 * Note that pidfd_leader is a thread-group pidfd, so polling on it
312 * would only notify us once all thread in the thread-group have
313 * exited. So we can't poll before we have taken down the whole
314 * thread-group.
315 */
316
317 /* Get PIDFD_GET_INFO using the thread-group leader pidfd. */
318 ASSERT_EQ(ioctl(pidfd_leader, PIDFD_GET_INFO, &info), 0);
319 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_CREDS));
320 /* Process has exited but not been reaped, so no PIDFD_INFO_EXIT information yet. */
321 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_EXIT));
322 ASSERT_EQ(info.pid, pid_leader);
323
324 /*
325 * Now retrieve the same info using the thread specific pidfd
326 * for the thread-group leader.
327 */
328 info2.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
329 ASSERT_EQ(ioctl(pidfd_leader_thread, PIDFD_GET_INFO, &info2), 0);
330 ASSERT_TRUE(!!(info2.mask & PIDFD_INFO_CREDS));
331 /* Process has exited but not been reaped, so no PIDFD_INFO_EXIT information yet. */
332 ASSERT_FALSE(!!(info2.mask & PIDFD_INFO_EXIT));
333 ASSERT_EQ(info2.pid, pid_leader);
334
335 /* Now try the thread-specific pidfd. */
336 ASSERT_EQ(ioctl(pidfd_thread, PIDFD_GET_INFO, &info), 0);
337 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_CREDS));
338 /* The thread hasn't exited, so no PIDFD_INFO_EXIT information yet. */
339 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_EXIT));
340 ASSERT_EQ(info.pid, pid_thread);
341
342 /*
343 * Take down the whole thread-group. The thread-group leader
344 * exited successfully but the thread will now be SIGKILLed.
345 * This must be reflected in the recorded exit information.
346 */
347 EXPECT_EQ(sys_pidfd_send_signal(pidfd_leader, SIGKILL, NULL, 0), 0);
348 EXPECT_EQ(sys_waitid(P_PIDFD, pidfd_leader, NULL, WEXITED), 0);
349
350 fds.events = POLLIN;
351 fds.fd = pidfd_leader;
352 nevents = poll(&fds, 1, -1);
353 ASSERT_EQ(nevents, 1);
354 ASSERT_TRUE(!!(fds.revents & POLLIN));
355 /* The thread-group leader has been reaped. */
356 ASSERT_TRUE(!!(fds.revents & POLLHUP));
357
358 /*
359 * Retrieve exit information for the thread-group leader via the
360 * thread-group leader pidfd.
361 */
362 info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
363 ASSERT_EQ(ioctl(pidfd_leader, PIDFD_GET_INFO, &info), 0);
364 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_CREDS));
365 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_EXIT));
366 /* Even though the thread-group exited successfully it will still report the group exit code. */
367 ASSERT_TRUE(WIFSIGNALED(info.exit_code));
368 ASSERT_EQ(WTERMSIG(info.exit_code), SIGKILL);
369
370 /*
371 * Retrieve exit information for the thread-group leader via the
372 * thread-specific pidfd.
373 */
374 info2.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
375 ASSERT_EQ(ioctl(pidfd_leader_thread, PIDFD_GET_INFO, &info2), 0);
376 ASSERT_FALSE(!!(info2.mask & PIDFD_INFO_CREDS));
377 ASSERT_TRUE(!!(info2.mask & PIDFD_INFO_EXIT));
378
379 /* Even though the thread-group exited successfully it will still report the group exit code. */
380 ASSERT_TRUE(WIFSIGNALED(info2.exit_code));
381 ASSERT_EQ(WTERMSIG(info2.exit_code), SIGKILL);
382
383 /* Retrieve exit information for the thread. */
384 info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
385 ASSERT_EQ(ioctl(pidfd_thread, PIDFD_GET_INFO, &info), 0);
386 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_CREDS));
387 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_EXIT));
388
389 /* The thread got SIGKILLed. */
390 ASSERT_TRUE(WIFSIGNALED(info.exit_code));
391 ASSERT_EQ(WTERMSIG(info.exit_code), SIGKILL);
392
393 EXPECT_EQ(close(pidfd_leader), 0);
394 EXPECT_EQ(close(pidfd_thread), 0);
395 }
396
pidfd_info_thread_exec(void * arg)397 static void *pidfd_info_thread_exec(void *arg)
398 {
399 pid_t pid_thread = gettid();
400 int ipc_socket = *(int *)arg;
401
402 /* Inform the grand-parent what the tid of this thread is. */
403 if (write_nointr(ipc_socket, &pid_thread, sizeof(pid_thread)) != sizeof(pid_thread))
404 return NULL;
405
406 if (read_nointr(ipc_socket, &pid_thread, sizeof(pid_thread)) != sizeof(pid_thread))
407 return NULL;
408
409 close(ipc_socket);
410
411 sys_execveat(AT_FDCWD, "pidfd_exec_helper", NULL, NULL, 0);
412 return NULL;
413 }
414
TEST_F(pidfd_info,thread_group_exec)415 TEST_F(pidfd_info, thread_group_exec)
416 {
417 pid_t pid_leader, pid_poller, pid_thread;
418 pthread_t thread;
419 int nevents, pidfd_leader, pidfd_leader_thread, pidfd_thread, ret;
420 int ipc_sockets[2];
421 struct pollfd fds = {};
422 struct pidfd_info info = {
423 .mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT,
424 };
425
426 ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
427 EXPECT_EQ(ret, 0);
428
429 pid_leader = create_child(&pidfd_leader, 0);
430 EXPECT_GE(pid_leader, 0);
431
432 if (pid_leader == 0) {
433 close(ipc_sockets[0]);
434
435 /* The thread will outlive the thread-group leader. */
436 if (pthread_create(&thread, NULL, pidfd_info_thread_exec, &ipc_sockets[1]))
437 syscall(__NR_exit, EXIT_FAILURE);
438
439 /* Make the thread-group leader exit prematurely. */
440 syscall(__NR_exit, EXIT_SUCCESS);
441 }
442
443 /* Open a thread-specific pidfd for the thread-group leader. */
444 pidfd_leader_thread = sys_pidfd_open(pid_leader, PIDFD_THREAD);
445 ASSERT_GE(pidfd_leader_thread, 0);
446
447 pid_poller = fork();
448 ASSERT_GE(pid_poller, 0);
449 if (pid_poller == 0) {
450 /*
451 * We can't poll and wait for the old thread-group
452 * leader to exit using a thread-specific pidfd. The
453 * thread-group leader exited prematurely and
454 * notification is delayed until all subthreads have
455 * exited.
456 *
457 * When the thread has execed it will taken over the old
458 * thread-group leaders struct pid. Calling poll after
459 * the thread execed will thus block again because a new
460 * thread-group has started.
461 */
462 fds.events = POLLIN;
463 fds.fd = pidfd_leader_thread;
464 nevents = poll(&fds, 1, 10000 /* wait 5 seconds */);
465 if (nevents != 0)
466 _exit(EXIT_FAILURE);
467 if (fds.revents & POLLIN)
468 _exit(EXIT_FAILURE);
469 if (fds.revents & POLLHUP)
470 _exit(EXIT_FAILURE);
471 _exit(EXIT_SUCCESS);
472 }
473
474 /* Retrieve the tid of the thread. */
475 EXPECT_EQ(close(ipc_sockets[1]), 0);
476 ASSERT_EQ(read_nointr(ipc_sockets[0], &pid_thread, sizeof(pid_thread)), sizeof(pid_thread));
477
478 /* Opening a thread as a PIDFD_THREAD must succeed. */
479 pidfd_thread = sys_pidfd_open(pid_thread, PIDFD_THREAD);
480 ASSERT_GE(pidfd_thread, 0);
481
482 /* Now that we've opened a thread-specific pidfd the thread can exec. */
483 ASSERT_EQ(write_nointr(ipc_sockets[0], &pid_thread, sizeof(pid_thread)), sizeof(pid_thread));
484 EXPECT_EQ(close(ipc_sockets[0]), 0);
485
486 ASSERT_EQ(wait_for_pid(pid_poller), 0);
487
488 /* Wait until the kernel has SIGKILLed the thread. */
489 fds.events = POLLHUP;
490 fds.fd = pidfd_thread;
491 nevents = poll(&fds, 1, -1);
492 ASSERT_EQ(nevents, 1);
493 /* The thread has been reaped. */
494 ASSERT_TRUE(!!(fds.revents & POLLHUP));
495
496 /* Retrieve thread-specific exit info from pidfd. */
497 ASSERT_EQ(ioctl(pidfd_thread, PIDFD_GET_INFO, &info), 0);
498 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_CREDS));
499 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_EXIT));
500 /*
501 * While the kernel will have SIGKILLed the whole thread-group
502 * during exec it will cause the individual threads to exit
503 * cleanly.
504 */
505 ASSERT_TRUE(WIFEXITED(info.exit_code));
506 ASSERT_EQ(WEXITSTATUS(info.exit_code), 0);
507
508 /*
509 * The thread-group leader is still alive, the thread has taken
510 * over its struct pid and thus its pid number.
511 */
512 info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
513 ASSERT_EQ(ioctl(pidfd_leader, PIDFD_GET_INFO, &info), 0);
514 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_CREDS));
515 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_EXIT));
516 ASSERT_EQ(info.pid, pid_leader);
517
518 /* Take down the thread-group leader. */
519 EXPECT_EQ(sys_pidfd_send_signal(pidfd_leader, SIGKILL, NULL, 0), 0);
520
521 /*
522 * Afte the exec we're dealing with an empty thread-group so now
523 * we must see an exit notification on the thread-specific pidfd
524 * for the thread-group leader as there's no subthread that can
525 * revive the struct pid.
526 */
527 fds.events = POLLIN;
528 fds.fd = pidfd_leader_thread;
529 nevents = poll(&fds, 1, -1);
530 ASSERT_EQ(nevents, 1);
531 ASSERT_TRUE(!!(fds.revents & POLLIN));
532 ASSERT_FALSE(!!(fds.revents & POLLHUP));
533
534 EXPECT_EQ(sys_waitid(P_PIDFD, pidfd_leader, NULL, WEXITED), 0);
535
536 /* Retrieve exit information for the thread-group leader. */
537 info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
538 ASSERT_EQ(ioctl(pidfd_leader, PIDFD_GET_INFO, &info), 0);
539 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_CREDS));
540 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_EXIT));
541
542 EXPECT_EQ(close(pidfd_leader), 0);
543 EXPECT_EQ(close(pidfd_thread), 0);
544 }
545
pidfd_info_thread_exec_sane(void * arg)546 static void *pidfd_info_thread_exec_sane(void *arg)
547 {
548 pid_t pid_thread = gettid();
549 int ipc_socket = *(int *)arg;
550
551 /* Inform the grand-parent what the tid of this thread is. */
552 if (write_nointr(ipc_socket, &pid_thread, sizeof(pid_thread)) != sizeof(pid_thread))
553 return NULL;
554
555 if (read_nointr(ipc_socket, &pid_thread, sizeof(pid_thread)) != sizeof(pid_thread))
556 return NULL;
557
558 close(ipc_socket);
559
560 sys_execveat(AT_FDCWD, "pidfd_exec_helper", NULL, NULL, 0);
561 return NULL;
562 }
563
TEST_F(pidfd_info,thread_group_exec_thread)564 TEST_F(pidfd_info, thread_group_exec_thread)
565 {
566 pid_t pid_leader, pid_poller, pid_thread;
567 pthread_t thread;
568 int nevents, pidfd_leader, pidfd_leader_thread, pidfd_thread, ret;
569 int ipc_sockets[2];
570 struct pollfd fds = {};
571 struct pidfd_info info = {
572 .mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT,
573 };
574
575 ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
576 EXPECT_EQ(ret, 0);
577
578 pid_leader = create_child(&pidfd_leader, 0);
579 EXPECT_GE(pid_leader, 0);
580
581 if (pid_leader == 0) {
582 close(ipc_sockets[0]);
583
584 /* The thread will outlive the thread-group leader. */
585 if (pthread_create(&thread, NULL, pidfd_info_thread_exec_sane, &ipc_sockets[1]))
586 syscall(__NR_exit, EXIT_FAILURE);
587
588 /*
589 * Pause the thread-group leader. It will be killed once
590 * the subthread execs.
591 */
592 pause();
593 syscall(__NR_exit, EXIT_SUCCESS);
594 }
595
596 /* Retrieve the tid of the thread. */
597 EXPECT_EQ(close(ipc_sockets[1]), 0);
598 ASSERT_EQ(read_nointr(ipc_sockets[0], &pid_thread, sizeof(pid_thread)), sizeof(pid_thread));
599
600 /* Opening a thread as a PIDFD_THREAD must succeed. */
601 pidfd_thread = sys_pidfd_open(pid_thread, PIDFD_THREAD);
602 ASSERT_GE(pidfd_thread, 0);
603
604 /* Open a thread-specific pidfd for the thread-group leader. */
605 pidfd_leader_thread = sys_pidfd_open(pid_leader, PIDFD_THREAD);
606 ASSERT_GE(pidfd_leader_thread, 0);
607
608 pid_poller = fork();
609 ASSERT_GE(pid_poller, 0);
610 if (pid_poller == 0) {
611 /*
612 * The subthread will now exec. The struct pid of the old
613 * thread-group leader will be assumed by the subthread which
614 * becomes the new thread-group leader. So no exit notification
615 * must be generated. Wait for 5 seconds and call it a success
616 * if no notification has been received.
617 */
618 fds.events = POLLIN;
619 fds.fd = pidfd_leader_thread;
620 nevents = poll(&fds, 1, 10000 /* wait 5 seconds */);
621 if (nevents != 0)
622 _exit(EXIT_FAILURE);
623 if (fds.revents & POLLIN)
624 _exit(EXIT_FAILURE);
625 if (fds.revents & POLLHUP)
626 _exit(EXIT_FAILURE);
627 _exit(EXIT_SUCCESS);
628 }
629
630 /* Now that we've opened a thread-specific pidfd the thread can exec. */
631 ASSERT_EQ(write_nointr(ipc_sockets[0], &pid_thread, sizeof(pid_thread)), sizeof(pid_thread));
632 EXPECT_EQ(close(ipc_sockets[0]), 0);
633 ASSERT_EQ(wait_for_pid(pid_poller), 0);
634
635 /* Wait until the kernel has SIGKILLed the thread. */
636 fds.events = POLLHUP;
637 fds.fd = pidfd_thread;
638 nevents = poll(&fds, 1, -1);
639 ASSERT_EQ(nevents, 1);
640 /* The thread has been reaped. */
641 ASSERT_TRUE(!!(fds.revents & POLLHUP));
642
643 /* Retrieve thread-specific exit info from pidfd. */
644 ASSERT_EQ(ioctl(pidfd_thread, PIDFD_GET_INFO, &info), 0);
645 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_CREDS));
646 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_EXIT));
647 /*
648 * While the kernel will have SIGKILLed the whole thread-group
649 * during exec it will cause the individual threads to exit
650 * cleanly.
651 */
652 ASSERT_TRUE(WIFEXITED(info.exit_code));
653 ASSERT_EQ(WEXITSTATUS(info.exit_code), 0);
654
655 /*
656 * The thread-group leader is still alive, the thread has taken
657 * over its struct pid and thus its pid number.
658 */
659 info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
660 ASSERT_EQ(ioctl(pidfd_leader, PIDFD_GET_INFO, &info), 0);
661 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_CREDS));
662 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_EXIT));
663 ASSERT_EQ(info.pid, pid_leader);
664
665 /* Take down the thread-group leader. */
666 EXPECT_EQ(sys_pidfd_send_signal(pidfd_leader, SIGKILL, NULL, 0), 0);
667
668 /*
669 * Afte the exec we're dealing with an empty thread-group so now
670 * we must see an exit notification on the thread-specific pidfd
671 * for the thread-group leader as there's no subthread that can
672 * revive the struct pid.
673 */
674 fds.events = POLLIN;
675 fds.fd = pidfd_leader_thread;
676 nevents = poll(&fds, 1, -1);
677 ASSERT_EQ(nevents, 1);
678 ASSERT_TRUE(!!(fds.revents & POLLIN));
679 ASSERT_FALSE(!!(fds.revents & POLLHUP));
680
681 EXPECT_EQ(sys_waitid(P_PIDFD, pidfd_leader, NULL, WEXITED), 0);
682
683 /* Retrieve exit information for the thread-group leader. */
684 info.mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_EXIT;
685 ASSERT_EQ(ioctl(pidfd_leader, PIDFD_GET_INFO, &info), 0);
686 ASSERT_FALSE(!!(info.mask & PIDFD_INFO_CREDS));
687 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_EXIT));
688
689 EXPECT_EQ(close(pidfd_leader), 0);
690 EXPECT_EQ(close(pidfd_thread), 0);
691 }
692
693 /*
694 * Test: PIDFD_INFO_SUPPORTED_MASK field
695 *
696 * Verify that when PIDFD_INFO_SUPPORTED_MASK is requested, the kernel
697 * returns the supported_mask field indicating which flags the kernel supports.
698 */
TEST(supported_mask_field)699 TEST(supported_mask_field)
700 {
701 struct pidfd_info info = {
702 .mask = PIDFD_INFO_SUPPORTED_MASK,
703 };
704 int pidfd;
705 pid_t pid;
706
707 pid = create_child(&pidfd, 0);
708 ASSERT_GE(pid, 0);
709
710 if (pid == 0)
711 pause();
712
713 /* Request supported_mask field */
714 ASSERT_EQ(ioctl(pidfd, PIDFD_GET_INFO, &info), 0);
715
716 /* Verify PIDFD_INFO_SUPPORTED_MASK is set in the reply */
717 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_SUPPORTED_MASK));
718
719 /* Verify supported_mask contains expected flags */
720 ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_PID));
721 ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_CREDS));
722 ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_CGROUPID));
723 ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_EXIT));
724 ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_COREDUMP));
725 ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_SUPPORTED_MASK));
726 ASSERT_TRUE(!!(info.supported_mask & PIDFD_INFO_COREDUMP_SIGNAL));
727
728 /* Clean up */
729 sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0);
730 sys_waitid(P_PIDFD, pidfd, NULL, WEXITED);
731 close(pidfd);
732 }
733
734 /*
735 * Test: PIDFD_INFO_SUPPORTED_MASK always available
736 *
737 * Verify that supported_mask is returned even when other fields are requested.
738 */
TEST(supported_mask_with_other_fields)739 TEST(supported_mask_with_other_fields)
740 {
741 struct pidfd_info info = {
742 .mask = PIDFD_INFO_CGROUPID | PIDFD_INFO_SUPPORTED_MASK,
743 };
744 int pidfd;
745 pid_t pid;
746
747 pid = create_child(&pidfd, 0);
748 ASSERT_GE(pid, 0);
749
750 if (pid == 0)
751 pause();
752
753 ASSERT_EQ(ioctl(pidfd, PIDFD_GET_INFO, &info), 0);
754
755 /* Both fields should be present */
756 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_CGROUPID));
757 ASSERT_TRUE(!!(info.mask & PIDFD_INFO_SUPPORTED_MASK));
758 ASSERT_NE(info.supported_mask, 0);
759
760 /* Clean up */
761 sys_pidfd_send_signal(pidfd, SIGKILL, NULL, 0);
762 sys_waitid(P_PIDFD, pidfd, NULL, WEXITED);
763 close(pidfd);
764 }
765
766 TEST_HARNESS_MAIN
767