Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+10 -6
+10 -6
include/linux/eventpoll.h
··· 39 39 { 40 40 41 41 /* 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. 48 52 */ 49 53 if (likely(!READ_ONCE(file->f_ep))) 50 54 return;