Deleting all PRL entries queues the old list for RCU freeing before t->prl is cleared. A reader that enters an RCU critical section after call_rcu() but before the pointer is cleared can still fetch the old list, and that critical section is not guaranteed to be covered by the grace period associated with the callback. RTNL does not prevent this race: RCU readers do not acquire it and the writer remains preemptible. It can lead to use-after-free. BUG: KASAN: slab-use-after-free in ipip6_rcv+0x165b/0x1d60 [sit] Read of size 4 at addr ffff888003aac488 by task poc38/3102 Allocated by task 3106: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 __kasan_kmalloc+0x8f/0xa0 __kmalloc_cache_noprof+0x158/0x370 ipip6_tunnel_siocdevprivate+0x96b/0xde0 [sit] dev_ifsioc+0x776/0x1530 dev_ioctl+0x6ca/0xdd0 sock_ioctl+0x42f/0x590 __x64_sys_ioctl+0x134/0x1c0 do_syscall_64+0xf9/0x540 entry_SYSCALL_64_after_hwframe+0x77/0x7f Freed by task 3100: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 kasan_save_free_info+0x3b/0x60 __kasan_slab_free+0x43/0x70 kfree+0x121/0x380 prl_list_destroy_rcu+0x32/0x60 [sit] rcu_core+0x50a/0x1740 handle_softirqs+0x18e/0x590 __irq_exit_rcu+0x60/0x130 sysvec_apic_timer_interrupt+0x36/0x80 asm_sysvec_apic_timer_interrupt+0x1a/0x20 Fix by clearing the publication pointer before call_rcu(). Fixes: ef9a9d1183b3 ("ipv6 sit: RCU conversion phase I") Signed-off-by: Binbin Deng <18983559317@163.com> --- net/ipv6/sit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 19b7fa8d1a2a..b850f06fd734 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -447,8 +447,8 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) x = rtnl_dereference(t->prl); if (x) { t->prl_count = 0; + RCU_INIT_POINTER(t->prl, NULL); call_rcu(&x->rcu_head, prl_list_destroy_rcu); - t->prl = NULL; } } out: -- 2.43.0