From: syzbot <syzbot+e70e1b6cba8714543f7c@syzkaller.appspotmail.com>
To: linux-kernel@vger.kernel.org
Subject: Forwarded: [PATCH] eventpoll: restore EP_UNACTIVE_PTR sentinel for ctx->tfile_check_list
Date: Thu, 28 May 2026 08:53:09 -0700 [thread overview]
Message-ID: <6a1864e5.556265cb.6a38.0000.GAE@google.com> (raw)
In-Reply-To: <6a10b30b.050a0220.19f61f.0003.GAE@google.com>
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org.
***
Subject: [PATCH] eventpoll: restore EP_UNACTIVE_PTR sentinel for ctx->tfile_check_list
Author: zhanwei919@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master
commit e09c77d94003 ("eventpoll: hoist CTL_ADD scratch state into
struct ep_ctl_ctx") moved tfile_check_list from file-scope global
to stack-allocated struct ep_ctl_ctx, replacing the EP_UNACTIVE_PTR
sentinel with NULL because "NULL is the obvious 'empty'
value and the zero-init handle it for free", and describe the
change "No functional change". but its not.
epitems_head->next is overload:
1: as a linked-list next pointer for heads on ctx->tfile_check_list,
2: as a membership flag: ep_remove_file() uses
!smp_load_acquire(&v->next) to mean "this head is not on any
pending ctx->tfile_check_list and is safe to free".
Before e09c77d94003, the EP_UNACTIVE_PTR sentinel made the two role
disjoint: a head on tfile_check_list always has a non-NULL next
(another head, or the sentinel), so v->next == NULL was equivalent
to never list. With the sentinel gone the list is NULL-terminated
and the tail head's ->next is NULL also. ep_remove_file()'s gate
no longer tell never list from list at the tail, and
misfires on the tail.
The reader hold epnested_mutex + rcu_read_lock; the freer hold
ep->mtx + file->f_lock. There is no sharing mutex between them; the
sentinel was the invariant the gate relied on to skip the read side.
The syzbot reproducer hit this within seconds on a multi-CPU VM.
Restore the sentinel: initialize ctx.tfile_check_list to
EP_UNACTIVE_PTR in do_epoll_ctl_file(), and walk it with
"!= EP_UNACTIVE_PTR" termination in reverse_path_check() and
clear_tfile_check_list(). The gate in ep_remove_file() regains its
never list exclusivity and stop misfiring on the tail.
ep_remove_file() itself does not change.
This restores the invariant the file-scope tfile_check_list relied
on before e09c77d94003, preserving the ctx packaging that commit
introduced.
Reported-by: syzbot+e70e1b6cba8714543f7c@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=e70e1b6cba8714543f7c
Fixes: e09c77d94003 ("eventpoll: hoist CTL_ADD scratch state into struct ep_ctl_ctx")
Suggested-by: Christian Brauner <brauner@kernel.org>
Link: https://lore.kernel.org/all/20260528-rotwild-summt-kuhhandel-7276ef4c33b7@brauner.io/
Signed-off-by: Zhan Wei <zhanwei919@gmail.com>
---
fs/eventpoll.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index a569e98d4a99..4973a5a5a3e1 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1685,7 +1685,7 @@ static int reverse_path_check(struct ep_ctl_ctx *ctx)
{
struct epitems_head *p;
- for (p = ctx->tfile_check_list; p; p = p->next) {
+ for (p = ctx->tfile_check_list; p != EP_UNACTIVE_PTR; p = p->next) {
int error;
path_count_init(ctx);
rcu_read_lock();
@@ -2438,7 +2438,7 @@ static int ep_loop_check(struct ep_ctl_ctx *ctx, struct eventpoll *ep,
static void clear_tfile_check_list(struct ep_ctl_ctx *ctx)
{
rcu_read_lock();
- while (ctx->tfile_check_list) {
+ while (ctx->tfile_check_list != EP_UNACTIVE_PTR) {
struct epitems_head *head = ctx->tfile_check_list;
ctx->tfile_check_list = head->next;
unlist_file(head);
@@ -2601,7 +2601,9 @@ int do_epoll_ctl_file(struct file *f, int op, struct epoll_key *tf,
int full_check;
struct eventpoll *ep;
struct epitem *epi;
- struct ep_ctl_ctx ctx = { };
+ struct ep_ctl_ctx ctx = {
+ .tfile_check_list = EP_UNACTIVE_PTR,
+ };
/* The target file descriptor must support poll */
if (!file_can_poll(tf->file))
--
2.43.0
next prev parent reply other threads:[~2026-05-28 15:53 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-22 19:48 [syzbot] [fs?] KASAN: slab-use-after-free Read in reverse_path_check_proc syzbot
2026-05-22 21:22 ` Hillf Danton
2026-05-22 23:31 ` syzbot
2026-05-28 15:53 ` syzbot [this message]
2026-05-29 13:24 ` Forwarded: [PATCH] eventpoll: restore EP_UNACTIVE_PTR sentinel for ctx->tfile_check_list syzbot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6a1864e5.556265cb.6a38.0000.GAE@google.com \
--to=syzbot+e70e1b6cba8714543f7c@syzkaller.appspotmail.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®