[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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help