[BUG] net: tun: NAPI-frags skb can be freed during a blocked write
From: Cheng Yongkang <hidden>
Date: 2026-10-22 09:07:03
Also in:
lkml
Hi all,
In the IFF_NAPI|IFF_NAPI_FRAGS write path, tun_napi_alloc_frags()
publishes tfile->napi.skb and skb_copy_datagram_from_iter() copies user
data before the writer enters the RCU section that teardown waits on.
tun_detach_all() does not take napi_mutex; after disabling NAPI and
calling synchronize_net(), tun_napi_del() can free the same skb through
napi_free_frags().
A userfaultfd-blocked write makes this race deterministic:
writer: napi_get_frags() publishes tfile->napi.skb
writer: sleeps in skb_copy_datagram_from_iter()
deleter: tun_net_uninit -> __netif_napi_del_locked
-> napi_free_frags() frees the skb
writer: resumes copying through the stale local skb pointer
Observed on Linux v7.3, commit
08ab31164c55f20c7a2653de3186ae333470e2c1, on three independent KASAN
boots:
BUG: KASAN: slab-use-after-free
Read of size 8 in skb_copy_datagram_from_iter
tun_get_user
tun_chr_write_iter
Freed by:
__netif_napi_del_locked
tun_net_uninit
unregister_netdevice_many_notify
rtnl_dellink
The already-held local skb pointer also reaches kfree_skb_reason() on
the later drop path, making a second free a direct consequence. The
first KASAN report stops the panic_on_warn kernel before that second
report is observed.
Allocation/use must be serialized with tun_napi_del() and device
unregister, rather than relying only on an RCU section entered after
the expensive user copy.
I found no matching upstream fix.
The userfaultfd reproducer and full console logs are available on
request.
This was found with AI-assisted source analysis and fuzzing; the UAF was
reproduced under KASAN.
Thanks,
Cheng Yongkang