Re: [BUG] KASAN: slab-use-after-free Write in sk_skb_reason_drop

Jiayuan Chen
2026-04-23T14:28:16Z

On 4/23/26 9:41 PM, Eulgyu Kim wrote:
> Hello,
>
> We encountered a "KASAN: slab-use-after-free Write in sk_skb_reason_drop"
> on kernel version v7.0.
>
> As this memory corruption bug seems to require `CAP_NET_ADMIN`,
> we report this in public mailing list.
>
> We have included the following items below:
> - C reproducer (~100 lines)
> - kernel delay patch
> - KASAN crash log
>
> To reliably trigger the race condition bug, we patched the kernel
> to inject a delay at a specific point.
>
> The kernel config used is the same as the syzbot configuration.
>
> Unfortunately, we do not have a fix ready for this bug yet.
> As this issue was identified via fuzzing and we have limited background,
> we find it challenging to propose a correct fix or evaluate
> its potential severity.
>
> We hope this report helps address the issue. Please let us know
> if any further information is needed.
>
> Thank you.
>
> Best Regards,
> Eulgyu Kim
>
>
>
> kernel delay patch:
> ==================================================================
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index c492fda6f..ba7078e18 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -1891,6 +1891,10 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
> !tfile->detached)
> rxhash = __skb_get_hash_symmetric(skb);
>
> + if (strcmp(current->comm, "slowme") == 0) {
> + mdelay(2000);
> + }
> +
> rcu_read_lock();
> if (unlikely(!(tun->dev->flags & IFF_UP))) {
> err = -EIO;
> ==================================================================
>

Hi Eulgyu,

I think this is caused by the lack of napi_mutex protection, and the
queue detach path seems to have the same issue.

The fix could be this:

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index b183189f1853..6a0bbd4def76 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -289,8 +289,12 @@ static void tun_napi_disable(struct tun_file *tfile)

static void tun_napi_del(struct tun_file *tfile)
{
-       if (tfile->napi_enabled)
-               netif_napi_del(&tfile->napi);
+       if (!tfile->napi_enabled)
+               return;
+
+       mutex_lock(&tfile->napi_mutex);
+       netif_napi_del(&tfile->napi);
+       mutex_unlock(&tfile->napi_mutex);
}

static bool tun_napi_frags_enabled(const struct tun_file *tfile)
@@ -1783,6 +1787,12 @@ static ssize_t tun_get_user(struct tun_struct
*tun, struct tun_file *tfile,

if (frags) {
mutex_lock(&tfile->napi_mutex);
+                       if (unlikely(tfile->detached ||
+ rcu_access_pointer(tfile->tun) != tun)) {
+                               err = -EBUSY;
+  mutex_unlock(&tfile->napi_mutex);
+                               goto out;
+                       }
skb = tun_napi_alloc_frags(tfile, copylen, from);
/* tun_napi_alloc_frags() enforces a layout for
the skb.
* If zerocopy is enabled, then this layout will be
@@ -1981,6 +1991,7 @@ static ssize_t tun_get_user(struct tun_struct
*tun, struct tun_file *tfile,
mutex_unlock(&tfile->napi_mutex);
}

+out:
return err ?: total_len;
}