Skip to content

Commit 33e92e9

Browse files
committed
eventpoll: refresh eventpoll_release() fast-path comment
The old comment justified the lockless READ_ONCE(file->f_ep) check with "False positives simply cannot happen because the file is on the way to be removed and nobody ( but eventpoll ) has still a reference to this file." That reasoning was the root of the UAF fixed in "eventpoll: fix ep_remove struct eventpoll / struct file UAF": __ep_remove() could clear f_ep while another close raced past the fast path and freed the watched eventpoll / recycled the struct file slot. With ep_remove() now pinning @file via epi_fget() across the f_ep clear and hlist_del_rcu(), the invariant is re-established for the right reason: anyone who might clear f_ep holds @file alive for the duration, so a NULL observation really does mean no concurrent eventpoll path has work left on this file. Refresh the comment accordingly so the next reader doesn't inherit the broken model. Link: https://patch.msgid.link/20260423-work-epoll-uaf-v1-8-2470f9eec0f5@kernel.org Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
1 parent d30deeb commit 33e92e9

1 file changed

Lines changed: 10 additions & 6 deletions

File tree

include/linux/eventpoll.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,16 @@ static inline void eventpoll_release(struct file *file)
3939
{
4040

4141
/*
42-
* Fast check to avoid the get/release of the semaphore. Since
43-
* we're doing this outside the semaphore lock, it might return
44-
* false negatives, but we don't care. It'll help in 99.99% of cases
45-
* to avoid the semaphore lock. False positives simply cannot happen
46-
* because the file in on the way to be removed and nobody ( but
47-
* eventpoll ) has still a reference to this file.
42+
* Fast check to skip the slow path in the common case where the
43+
* file was never attached to an epoll. Safe without file->f_lock
44+
* because every f_ep writer excludes a concurrent __fput() on
45+
* @file:
46+
* - ep_insert() requires the file alive (refcount > 0);
47+
* - ep_remove() holds @file pinned via epi_fget() across the
48+
* write;
49+
* - eventpoll_release_file() runs from __fput() itself.
50+
* We are in __fput() here, so none of those can race us: a NULL
51+
* observation truly means no epoll path has work left on @file.
4852
*/
4953
if (likely(!READ_ONCE(file->f_ep)))
5054
return;

0 commit comments

Comments
 (0)