[PATCH next] eventpoll: delay file list memory deallocation until unlisting

Edward Adam Davis posted 1 patch 7 hours ago
fs/eventpoll.c | 2 ++
1 file changed, 2 insertions(+)
[PATCH next] eventpoll: delay file list memory deallocation until unlisting
Posted by Edward Adam Davis 7 hours ago
Commit e09c77d94003 implicitly sets the head->next value within list_file()
to NULL; this occurs because ctx->tfile_check_list which resides on the stack
is initialized to NULL. This introduces a potential risk to ep_remove_file(),
as the decision to reclaim epitems_head depends solely on whether the next
pointer is NULL. Prior to the introduction of e09c77d94003, the presence of
the sentinel value EP_UNACTIVE_PTR prevented the next pointer from becoming
NULL prematurely; the next value would only be updated to NULL during the
execution of unlist_file(). 
However, following the introduction of e09c77d94003, list_file() also updates
the next value to NULL, which ultimately led to the uaf reported in [1].

To mitigate the risk posed by the potentially NULL next pointer, the memory
reclamation for the file list originally performed within ep_remove_file()
has been deferred to unlist_file().

[1]
BUG: KASAN: slab-use-after-free in clear_tfile_check_list+0x114/0x380 fs/eventpoll.c:2443
Read of size 8 at addr ffff88803f021568 by task syz.0.74/5985
Call Trace:
 clear_tfile_check_list+0x114/0x380 fs/eventpoll.c:2443
 do_epoll_ctl_file+0x8fd/0xed0 fs/eventpoll.c:-1
 
Allocated by task 5985:
 ep_attach_file fs/eventpoll.c:1751 [inline]
 ep_register_epitem fs/eventpoll.c:1833 [inline]
 ep_insert+0x512/0x1820 fs/eventpoll.c:1876
 do_epoll_ctl_file+0x8bb/0xed0 fs/eventpoll.c:2651
 
Freed by task 5985:
 kmem_cache_free+0x187/0x6c0 mm/slub.c:6411
 ep_remove+0x155/0x2a0 fs/eventpoll.c:1135
 ep_insert+0x1372/0x1820 fs/eventpoll.c:-1
 do_epoll_ctl_file+0x8bb/0xed0 fs/eventpoll.c:2651

Fixes: e09c77d94003 ("eventpoll: hoist CTL_ADD scratch state into struct ep_ctl_ctx")
Reported-by: syzbot+69a3d7738ad3aa175caf@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=69a3d7738ad3aa175caf
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
 fs/eventpoll.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index a569e98d4a99..66aa4f200909 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1080,6 +1080,8 @@ static void ep_remove_file(struct eventpoll *ep, struct epitem *epi,
 			v = container_of(head, struct epitems_head, epitems);
 			if (!smp_load_acquire(&v->next))
 				to_free = v;
+			if (!hlist_empty(&v->epitems))
+				to_free = NULL;
 		}
 	}
 	hlist_del_rcu(&epi->fllink);
-- 
2.43.0