[STABLE v5.15.y 2/8] eventpoll: use hlist_is_singular_node() in __ep_remove()

From: Lee Jones

Date: Tue Sep 08 2026 - 05:09:49 EST


From: Christian Brauner <brauner@xxxxxxxxxx>

[ Upstream commit 3d9fd0abc94d8cd430cc7cd7d37ce5e5aae2cd2b ]

Replace the open-coded "epi is the only entry in file->f_ep" check
with hlist_is_singular_node(). Same semantics, and the helper avoids
the head-cacheline access in the common false case.

Link: https://patch.msgid.link/20260423-work-epoll-uaf-v1-1-2470f9eec0f5@xxxxxxxxxx
Signed-off-by: Christian Brauner (Amutable) <brauner@xxxxxxxxxx>
Stable-dep-of: a6dc643c6931 ("eventpoll: fix ep_remove struct eventpoll / struct file UAF")
Signed-off-by: Quentin Schulz <quentin.schulz@xxxxxxxxx>
Signed-off-by: Wentao Guan <guanwentao@xxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
(cherry picked from commit 605963b245b2c436803cbbefddf5ee5cb326ceaa)
Signed-off-by: Lee Jones <lee@xxxxxxxxxx>
---
fs/eventpoll.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 8762d0908637..5945390e352c 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -738,7 +738,7 @@ static bool __ep_remove(struct eventpoll *ep, struct epitem *epi, bool force)

to_free = NULL;
head = file->f_ep;
- if (head->first == &epi->fllink && !epi->fllink.next) {
+ if (hlist_is_singular_node(&epi->fllink, head)) {
/* See eventpoll_release() for details. */
WRITE_ONCE(file->f_ep, NULL);
if (!is_file_epoll(file)) {
--
2.55.0.979.g7e5102b832-goog