From 7ab18c2db0f15fa48d1e494a5063472b874dba4f Mon Sep 17 00:00:00 2001 From: "Terence Tritton (xWF)" Date: Mon, 14 Oct 2024 12:25:32 +0000 Subject: [PATCH] Reapply "pidfd_poll: report POLLHUP when pid_task() == NULL" This reverts commit d3ec16ca12e27d8a5772dcade0fb19da5ab5bc0b. Reason of revert: Fix has been applied to lmkd to handle EPOLLHUP - aosp/3268491 Change-Id: I24e17e778ff013adcbf1a6ad43470adc8d9f19cb Signed-off-by: Terence Tritton Bug: 352286227 --- fs/pidfs.c | 26 +++++++------------------- kernel/pid.c | 5 +++++ 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/fs/pidfs.c b/fs/pidfs.c index 257924f379af..80675b6bf884 100644 --- a/fs/pidfs.c +++ b/fs/pidfs.c @@ -89,23 +89,6 @@ static void pidfd_show_fdinfo(struct seq_file *m, struct file *f) } #endif - -static bool pidfd_task_exited(struct pid *pid, bool thread) -{ - struct task_struct *task; - bool exited; - - rcu_read_lock(); - task = pid_task(pid, PIDTYPE_PID); - exited = !task || - (READ_ONCE(task->exit_state) && (thread || thread_group_empty(task))); - rcu_read_unlock(); - - return exited; -} - - - /* * Poll support for process exit notification. */ @@ -113,6 +96,7 @@ static __poll_t pidfd_poll(struct file *file, struct poll_table_struct *pts) { struct pid *pid = pidfd_pid(file); bool thread = file->f_flags & PIDFD_THREAD; + struct task_struct *task; __poll_t poll_flags = 0; poll_wait(file, &pid->wait_pidfd, pts); @@ -120,8 +104,12 @@ static __poll_t pidfd_poll(struct file *file, struct poll_table_struct *pts) * Depending on PIDFD_THREAD, inform pollers when the thread * or the whole thread-group exits. */ - if(pidfd_task_exited(pid, thread)) - poll_flags = EPOLLIN | EPOLLRDNORM; + guard(rcu)(); + task = pid_task(pid, PIDTYPE_PID); + if (!task) + poll_flags = EPOLLIN | EPOLLRDNORM | EPOLLHUP; + else if (task->exit_state && (thread || thread_group_empty(task))) + poll_flags = EPOLLIN | EPOLLRDNORM; return poll_flags; } diff --git a/kernel/pid.c b/kernel/pid.c index 58cbb6c7a3ec..d15fb6c3fe89 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -355,6 +355,11 @@ static void __change_pid(struct task_struct *task, enum pid_type type, hlist_del_rcu(&task->pid_links[type]); *pid_ptr = new; + if (type == PIDTYPE_PID) { + WARN_ON_ONCE(pid_has_task(pid, PIDTYPE_PID)); + wake_up_all(&pid->wait_pidfd); + } + for (tmp = PIDTYPE_MAX; --tmp >= 0; ) if (pid_has_task(pid, tmp)) return;