File Index
Files and directories
Sign in
FILE

pidfd_info_test.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/pidfd/pidfd_info_test.c C
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#define _GNU_SOURCE
  4#include <errno.h>
  5#include <fcntl.h>
  6#include <limits.h>
  7#include <linux/types.h>
  8#include <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
 26FIXTURE(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
 41FIXTURE_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
113FIXTURE_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
130TEST_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
146TEST_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
164TEST_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
180TEST_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
198TEST_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
221static 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
237TEST_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
397static 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
415TEST_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
546static 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
564TEST_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 */
699TEST(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 */
739TEST(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
766TEST_HARNESS_MAIN
~/ Read-only file preview.