From: sashiko-bot@kernel.org
To: "Jiayuan Chen" <jiayuan.chen@linux.dev>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH net v1] bpf: cpumap: fix use-after-free of dev_rx on netdev unregister
Date: Mon, 21 Sep 2026 13:31:21 +0000 [thread overview]
Message-ID: <20260921133122.5EF3E1F0089A@smtp.kernel.org> (raw)
In-Reply-To: <20260920133017.248620-1-jiayuan.chen@linux.dev>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] bpf: cpumap: UAF of netdev due to unlinking dying entry before kthread stop
- [High] bpf: cpumap: TOCTOU race in dev unregistering check allows UAF via chained redirects
--
commit 357385e1a9c647836291f6c8f562ac50211ab22f
Author: Jiayuan Chen <jiayuan.chen@linux.dev>
bpf: cpumap: fix use-after-free of dev_rx on netdev unregister
This commit adds a netdev unregister notifier to drain cpumap kthreads to
prevent use-after-free of stale netdev pointers in queued frames. It forces
kthreads to consume existing frames and flush GRO caches before unregistration
completes. It also checks for unregistered devices during cpumap redirects to
drop stale packets.
> diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c
> index 5e59ab896f058..bc2186adcd9a4 100644
> --- a/kernel/bpf/cpumap.c
> +++ b/kernel/bpf/cpumap.c
[ ... ]
> @@ -153,6 +171,11 @@ static u32 cpu_map_bpf_prog_run_skb(struct bpf_cpu_map_entry *rcpu,
> skbs[pass++] = skb;
> break;
> case XDP_REDIRECT:
> + if (cpu_map_dev_unregistering(skb->dev)) {
> + kfree_skb(skb);
> + stats->drop++;
> + break;
> + }
[Severity: High]
Is there a time-of-check to time-of-use (TOCTOU) race here when chaining
cpumap-to-cpumap redirects?
During a redirect from cpumap A to cpumap B, kthread A might check
cpu_map_dev_unregistering() and see the device is still registered, then get
preempted.
A netdev unregister could then trigger the notifier, which sets drain_left
for all kthreads and starts waiting. Kthread B might wake up, find its queue
empty, report drain_left = 0, and wake the notifier.
Then kthread A resumes, enqueues its packet to cpumap B, finishes its batch,
reports drain_left = 0, and wakes the notifier.
Since the notifier checks the wait queues one-by-one independently in
cpu_map_netdev_event():
list_for_each_entry(rcpu, &cpu_map_list, list)
wait_event(rcpu->drain_wq, !READ_ONCE(rcpu->drain_left));
It could unblock because both queues eventually reported 0, allowing the
netdev to be freed. Kthread B could then wake up to process the newly
enqueued packet, leading to a use-after-free on the netdevice.
> err = xdp_do_generic_redirect(skb->dev, skb, &xdp,
> rcpu->prog);
[ ... ]
> @@ -528,6 +576,11 @@ static void __cpu_map_entry_free(struct work_struct *work)
> */
> rcpu = container_of(to_rcu_work(work), struct bpf_cpu_map_entry, free_work);
>
> + /* Unlink first, so the notifier can't wait on a kthread we stop */
> + mutex_lock(&cpu_map_mutex);
> + list_del(&rcpu->list);
> + mutex_unlock(&cpu_map_mutex);
> +
[Severity: High]
Does unlinking this entry before stopping the kthread open a window for a
use-after-free?
If a netdev unregister happens concurrently with a map update freeing this
entry, cpu_map_netdev_event() will iterate over cpu_map_list.
Since the entry is already removed from the list via list_del(), the notifier
won't wait for this dying kthread to drain.
The netdevice can then be freed, but the kthread could still be processing
its queue while shutting down via kthread_stop(), potentially accessing the
freed netdevice through xdpf->dev_rx or skb->dev.
> /* kthread_stop will wake_up_process and wait for it to complete.
> * cpu_map_kthread_run() makes sure the pointer ring is empty
> * before exiting.
> */
> kthread_stop(rcpu->kthread);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260920133017.248620-1-jiayuan.chen@linux.dev?part=1
prev parent reply other threads:[~2026-09-21 13:31 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-20 13:30 [PATCH net v1] bpf: cpumap: fix use-after-free of dev_rx on netdev unregister Jiayuan Chen
2026-09-20 16:17 ` Alexei Starovoitov
2026-09-21 13:31 ` sashiko-bot [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260921133122.5EF3E1F0089A@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=jiayuan.chen@linux.dev \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox