diff options
| author | Josef Bacik <josef@toxicpanda.com> | 2026-10-04 15:00:12 +0000 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-10-29 15:48:52 +0100 |
| commit | 172658cf600904ff6121e240f69a0ccb36e65d6b (patch) | |
| tree | 67cf519d68d43bb4f8d7e602cd9422888bde1abf /include | |
| parent | da29ac46d34a19e8cc328ad17cb88713fd4563fa (diff) | |
pidfs: don't let PIDFD_GET_INFO miss a reaped task
PIDFD_GET_INFO describes the task while there is one, and with
PIDFD_INFO_EXIT its exit status once it has been reaped. pidfd_info()
looks at the two in the wrong order and can miss both:
pidfd_info() release_task()
PIDFS_ATTR_BIT_EXIT is not set
pidfs_exit()
__unhash_process()
get_pid_task() == NULL
goto copy_out
The ioctl succeeds with neither PIDFD_INFO_PID nor PIDFD_INFO_EXIT in the
mask. If the task is unhashed a little later, after get_pid_task(), its
pid reads as 0 and the ioctl fails with -ESRCH, although the caller asked
for the exit information and it is available by now.
The second case does not even need an exit. When a sub-thread execs,
de_thread() hands the leader's pid over to it and releases the old leader.
A caller that got hold of the old leader reports the tid of the sub-thread
as the pid, or -ESRCH for a process that is alive.
Look up the task first. pidfs_exit() runs before the task is unhashed, so
a caller that finds no task finds the exit information; this needs a
barrier on both sides because taking tasklist_lock does not order the
store in pidfs_exit() against the one in detach_pid(). And start over if
the task no longer owns the pid when all the fields have been read: then
there is either exit information or another task.
Go by the pid for that check and for the pid we report, not by
->thread_pid of the task. exchange_tids() moves the pid to the exec'ing
thread before it updates ->thread_pid of either task. A caller that
finds the new leader in between would read the old tid of the sub-thread
from ->thread_pid, and a check of ->thread_pid would restart until the
exec'ing thread gets to its store. On PREEMPT_RT that thread can be
preempted with tasklist_lock held and can't move to another CPU. If the
RT task that preempted it calls PIDFD_GET_INFO, the ioctl spins until
the exec'ing thread gets the CPU back, and that never happens if the
exec'ing thread is an RT task of lower priority.
Christian Brauner <brauner@kernel.org> says:
Go by @pid instead of ->thread_pid of the task for the reported pid and
for the restart check.
Fixes: 7477d7dce48a ("pidfs: allow to retrieve exit information")
Fixes: cdda1f26e74b ("pidfd: add ioctl to retrieve pid info")
Cc: stable@vger.kernel.org
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Diffstat (limited to 'include')
0 files changed, 0 insertions, 0 deletions
