Thread (5 messages) 5 messages, 4 authors, 2026-09-25

Re: [PATCH net-next] net: devmem: use page_pool_put_netmem_bulk

flat view

From: Mina Almasry <hidden>
Date: 2026-09-25 12:49:45
Also in: lkml

On Thu, Sep 24, 2026 at 3:36 PM [off-list ref] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider.

Critical: 0 · High: 1 · Medium: 0 · Low: 0

If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).

- [High] sock_devmem_dontneed() (net/core/sock.c) now releases the last
  page_pool reference of devmem net_iovs via…

--

net: devmem: use page_pool_put_netmem_bulk

This converts sock_devmem_dontneed() from a loop of napi_pp_put_page()
calls to a single page_pool_put_netmem_bulk() call per batch, so the
page_pool ring producer lock is taken once per batch instead of once per
netmem.
quoted
diff --git a/net/core/sock.c b/net/core/sock.c
index 2948dffcc3e1b..a6b6d5b2051df 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
[ ... ]
quoted
@@ -1123,8 +1124,7 @@ sock_devmem_dontneed(struct sock *sk, sockptr_t optval, unsigned int optlen)
                      netmems[netmem_num++] = netmem;
                      if (netmem_num == ARRAY_SIZE(netmems)) {
                              xa_unlock_bh(&sk->sk_user_frags);
-                             for (k = 0; k < netmem_num; k++)
-                                     WARN_ON_ONCE(!napi_pp_put_page(netmems[k]));
+                             page_pool_put_netmem_bulk(netmems, ARRAY_SIZE(netmems));
[Severity: High]
Can this reintroduce the page_pool use-after-free that commit
271683bb2cf32e ("page_pool: Fix use-after-free in
page_pool_recycle_in_ring") addressed, when CONFIG_PAGE_POOL_STATS=y?

The old path went through napi_pp_put_page() ->
page_pool_put_unrefed_netmem() -> page_pool_recycle_in_ring(), which
updates the stat while still holding the producer lock:

net/core/page_pool.c:page_pool_recycle_in_ring() {
        in_softirq = page_pool_producer_lock(pool);
        ret = !__ptr_ring_produce(&pool->ring, (__force void *)netmem);
        if (ret)
                recycle_stat_inc(pool, ring);
        page_pool_producer_unlock(pool, in_softirq);
}

The bulk path touches the pool after the unlock:

net/core/page_pool.c:page_pool_recycle_ring_bulk() {
        ...
        page_pool_producer_unlock(pool, in_softirq);
        recycle_stat_add(pool, ring, i);

Once the netmems are published into pool->ring, does the setsockopt
thread still hold anything that keeps the pool alive?  The barrier in
page_pool_release() only covers work done inside the producer lock:

net/core/page_pool.c:page_pool_release() {
        page_pool_scrub(pool);
        inflight = page_pool_inflight(pool, true);
        /* Acquire producer lock to make sure producers have exited. */
        in_softirq = page_pool_producer_lock(pool);
        page_pool_producer_unlock(pool, in_softirq);
        if (!inflight)
                __page_pool_destroy(pool);
}

so the sequence would be:

CPU0 (setsockopt SO_DEVMEM_DONTNEED)
  page_pool_put_netmem_bulk()
    page_pool_recycle_ring_bulk()
      __ptr_ring_produce()          /* last inflight refs published */
      page_pool_producer_unlock()   /* spin_unlock_bh(): BH/preempt window */

CPU1 (page_pool_release_retry() worker after deferred destroy)
  page_pool_release()
    page_pool_scrub() -> page_pool_empty_ring() -> page_pool_return_netmem()
    page_pool_inflight() == 0
    producer lock taken/released uncontended
    __page_pool_destroy() -> page_pool_uninit()
      free_percpu(pool->recycle_stats); kfree(pool);

CPU0
      recycle_stat_add(pool, ring, i);   /* this_cpu_add on freed memory */

Since the release is driven here by returning the last outstanding user
tokens, would it be better to move recycle_stat_add(pool, ring, i) inside
the producer-lock section of page_pool_recycle_ring_bulk() (matching
page_pool_recycle_in_ring()) before converting sock_devmem_dontneed() to
the bulk helper?
Thank you my dear bot. This seems like a real issue, a latent bug in
the *_bulk() put. Let me use my pet LLM to develop a fix for this,
send to net, and then respin this.

Lets hold onto this for now Kaifeng, and resubmit after my fix goes into net.

-- 
Thanks,
Mina
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help