mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 22:24:11 +08:00
pidfd: getfd should always report ESRCH if a task is exiting
We can get EBADF from pidfd_getfd() if a task is currently exiting, which might be confusing. Let's check PF_EXITING, and just report ESRCH if so. I chose PF_EXITING, because it is set in exit_signals(), which is called before exit_files(). Since ->exit_status is mostly set after exit_files() in exit_notify(), using that still leaves a window open for the race. Reviewed-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Tycho Andersen <tandersen@netflix.com> Link: https://lore.kernel.org/r/20240206192357.81942-1-tycho@tycho.pizza Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
parent
83b290c9e3
commit
0c9bd6bc4b
21
kernel/pid.c
21
kernel/pid.c
@ -678,7 +678,26 @@ static struct file *__pidfd_fget(struct task_struct *task, int fd)
|
||||
|
||||
up_read(&task->signal->exec_update_lock);
|
||||
|
||||
return file ?: ERR_PTR(-EBADF);
|
||||
if (!file) {
|
||||
/*
|
||||
* It is possible that the target thread is exiting; it can be
|
||||
* either:
|
||||
* 1. before exit_signals(), which gives a real fd
|
||||
* 2. before exit_files() takes the task_lock() gives a real fd
|
||||
* 3. after exit_files() releases task_lock(), ->files is NULL;
|
||||
* this has PF_EXITING, since it was set in exit_signals(),
|
||||
* __pidfd_fget() returns EBADF.
|
||||
* In case 3 we get EBADF, but that really means ESRCH, since
|
||||
* the task is currently exiting and has freed its files
|
||||
* struct, so we fix it up.
|
||||
*/
|
||||
if (task->flags & PF_EXITING)
|
||||
file = ERR_PTR(-ESRCH);
|
||||
else
|
||||
file = ERR_PTR(-EBADF);
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
static int pidfd_getfd(struct pid *pid, int fd)
|
||||
|
Loading…
Reference in New Issue
Block a user