Messages in this thread Patch in this message | ![/](/images/icornerl.gif) | | From | Eric Dumazet <> | Date | Mon, 20 Mar 2023 14:17:50 -0700 | Subject | syzbot + epoll |
| |
This is about this recent syzbot report (with a C repro)
https://lore.kernel.org/lkml/000000000000c6dc0305f75b4d74@google.com/T/#u
I think this is caused by:
commit fc02a95bb6d8bf58c6efd7e362814558eea2ef28 Author: Paolo Abeni <pabeni@redhat.com> Date: Tue Mar 7 19:46:37 2023 +0100
epoll: use refcount to reduce ep_mutex contention
Problem is that __ep_remove() might return early, without removing epi from the rbtree (ep->rbr)
This happens when epi->dying has been set to true here :
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/fs/eventpoll.c?id=6f72958a49f68553f2b6ff713e8c8e51a34c1e1e#n954
So we loop, while holding the ep->mtx held, meaning that the other thread is blocked here
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/fs/eventpoll.c?id=6f72958a49f68553f2b6ff713e8c8e51a34c1e1e#n962
So this dead locks.
Maybe fix this with:
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 25a59640748a0fd22a84a5aecb90815fbbca9cef..1db56c6175aab5af7bc637a452b68ed8bc11fd7f 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -784,7 +784,7 @@ static void ep_remove_safe(struct eventpoll *ep, struct epitem *epi)
static void ep_clear_and_put(struct eventpoll *ep) { - struct rb_node *rbp; + struct rb_node *rbp, *next; struct epitem *epi; bool dispose;
@@ -810,7 +810,8 @@ static void ep_clear_and_put(struct eventpoll *ep) * Since we still own a reference to the eventpoll struct, the loop can't * dispose it. */ - while ((rbp = rb_first_cached(&ep->rbr)) != NULL) { + for (rbp = rb_first_cached(&ep->rbr); rbp; rbp = next) { + next = rb_next(rbp); epi = rb_entry(rbp, struct epitem, rbn); ep_remove_safe(ep, epi); cond_resched();
| ![\](/images/icornerr.gif) |