mirror-linux/net/core
Hasan Basbunar 5ef343614d page_pool: fix memory-provider leak in page_pool_create_percpu() error path
When page_pool_create_percpu() fails on page_pool_list(), it falls
through to its err_uninit: label, which calls page_pool_uninit().
At that point page_pool_init() has already taken two references
when the user requested PP_FLAG_ALLOW_UNREADABLE_NETMEM:

	pool->mp_ops->init(pool)
	static_branch_inc(&page_pool_mem_providers);

Neither is undone by page_pool_uninit(); both are only undone by
__page_pool_destroy() (success-side teardown). The error path
therefore leaks the per-provider reference taken by mp_ops->init
(io_zcrx_ifq->refs in the io_uring zcrx provider, the dmabuf
binding refcount in the devmem provider) plus one increment of
the page_pool_mem_providers static branch on every failure of
xa_alloc_cyclic() inside page_pool_list().

The leaked io_zcrx_ifq->refs in turn pins everything
io_zcrx_ifq_free() would release on cleanup: ifq->user (uid),
ifq->mm_account (mmdrop), ifq->dev (device refcount),
ifq->netdev_tracker (netdev refcount), and the rbuf region.
The leaked static branch increment forces all subsequent
page_pool_alloc_netmems() and page_pool_return_page() callers to
take the slow mp_ops branch for the lifetime of the kernel.

Reachable via the io_uring zcrx path:

	io_uring_register(IORING_REGISTER_ZCRX_IFQ)  /* CAP_NET_ADMIN */
	  -> __io_uring_register
	  -> io_register_zcrx
	  -> zcrx_register_netdev
	  -> netif_mp_open_rxq
	  -> driver ndo_queue_mem_alloc
	  -> page_pool_create_percpu
	    -> page_pool_init succeeds (mp_ops->init runs, branch++)
	    -> page_pool_list fails (xa_alloc_cyclic -ENOMEM)
	    -> goto err_uninit         <-- leak

The same shape applies to the devmem dmabuf provider via
mp_dmabuf_devmem_init()/mp_dmabuf_devmem_destroy().

Restore the cleanup symmetry by moving the mp_ops->destroy() and
static_branch_dec() calls out of __page_pool_destroy() and into
page_pool_uninit(), so page_pool_uninit() is again the strict
inverse of page_pool_init(). page_pool_uninit() has only two
callers (the err_uninit: path and __page_pool_destroy()), so this
preserves the single-call invariant on the success path while
fixing the err path. The error path of page_pool_init() itself
still skips the mp_ops cleanup correctly: mp_ops->init is the
last action that takes a reference before page_pool_init() returns
0, so when it returns an error neither the refcount nor the static
branch has been touched.

Triggering the bug requires xa_alloc_cyclic() to fail with -ENOMEM,
which under normal GFP_KERNEL retry behaviour is rare. It is
deterministic under CONFIG_FAULT_INJECTION with fail_page_alloc /
xa fault injection, or under sustained memory pressure. The leak
is silent: there is no warning, and the released kernel build
continues running with a permanently-incremented static branch.

Fixes: 0f92140468 ("memory-provider: dmabuf devmem memory provider")
Signed-off-by: Hasan Basbunar <basbunarhasan@gmail.com>
Link: https://patch.msgid.link/20260428170739.34881-1-basbunarhasan@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-04-29 19:11:49 -07:00
..
Makefile net: get rid of net/core/request_sock.c 2026-02-05 09:23:05 -08:00
bpf_sk_storage.c bpf: Remove gfp_flags plumbing from bpf_local_storage_update() 2026-04-10 21:22:32 -07:00
datagram.c net: datagram: introduce datagram_poll_queue for custom receive queues 2025-10-23 15:46:04 +02:00
dev.c Delete some obsolete networking code 2026-04-24 09:41:58 -07:00
dev.h net: introduce ndo_set_rx_mode_async and netdev_rx_mode_work 2026-04-21 12:50:03 +02:00
dev_addr_lists.c net: warn ops-locked drivers still using ndo_set_rx_mode 2026-04-21 12:50:25 +02:00
dev_addr_lists_test.c net: cache snapshot entries for ndo_set_rx_mode_async 2026-04-21 12:50:13 +02:00
dev_api.c net: introduce ndo_set_rx_mode_async and netdev_rx_mode_work 2026-04-21 12:50:03 +02:00
dev_ioctl.c net: introduce ndo_set_rx_mode_async and netdev_rx_mode_work 2026-04-21 12:50:03 +02:00
devmem.c net: add net_iov_init() and use it to initialize ->page_type 2026-04-29 16:40:08 -07:00
devmem.h net: inline net_is_devmem_iov() 2026-01-25 13:18:53 -08:00
drop_monitor.c Convert more 'alloc_obj' cases to default GFP_KERNEL arguments 2026-02-21 20:03:00 -08:00
dst.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
dst_cache.c net: dst: annotate data-races around dst->obsolete 2025-07-02 14:32:29 -07:00
failover.c net: core: failover: enforce mandatory ops and clean up redundant checks 2026-03-03 17:44:11 -08:00
fib_notifier.c net: Add SPDX ids to some source files 2026-03-09 18:32:45 -07:00
fib_rules.c
filter.c Including fixes from Netfilter. 2026-04-23 16:50:42 -07:00
flow_dissector.c flow_dissector: do not dissect PPPoE PFC frames 2026-04-20 11:35:16 -07:00
flow_offload.c Convert more 'alloc_obj' cases to default GFP_KERNEL arguments 2026-02-21 20:03:00 -08:00
gen_estimator.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
gen_stats.c
gro.c net/ipv6: Drop HBH for BIG TCP on RX side 2026-02-06 20:50:12 -08:00
gro_cells.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
gso.c
hotdata.c net: remove EXPORT_IPV6_MOD() and EXPORT_IPV6_MOD_GPL() macros 2026-03-29 11:21:22 -07:00
hwbm.c
ieee8021q_helpers.c net: ieee8021q: fix insufficient table-size assertion 2025-07-01 12:55:49 +02:00
link_watch.c net/sched: do not reset queues in graft operations 2026-03-09 18:55:55 -07:00
lock_debug.c
lwt_bpf.c bpf: remove ipv6_bpf_stub completely and use direct function calls 2026-03-29 11:21:24 -07:00
lwtunnel.c
mp_dmabuf_devmem.h
neighbour.c neigh: let neigh_xmit take skb ownership 2026-04-27 19:02:11 -07:00
net-procfs.c net: add proper RCU protection to /proc/net/ptype 2026-02-03 19:20:30 -08:00
net-sysfs.c Networking changes for 7.1. 2026-04-14 18:36:10 -07:00
net-sysfs.h net: add skb_defer_disable_key static key 2026-03-12 19:25:33 -07:00
net-traces.c
net_namespace.c Networking changes for 7.1. 2026-04-14 18:36:10 -07:00
net_test.c
netclassid_cgroup.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
netdev-genl-gen.c net: Add queue-create operation 2026-04-09 18:21:45 -07:00
netdev-genl-gen.h net: Add queue-create operation 2026-04-09 18:21:45 -07:00
netdev-genl.c net: remove the netif_get_rx_queue_lease_locked() helpers 2026-04-09 18:26:28 -07:00
netdev_config.c net: add queue config validation callback 2026-01-23 11:49:02 -08:00
netdev_queues.c net: remove the netif_get_rx_queue_lease_locked() helpers 2026-04-09 18:26:28 -07:00
netdev_rx_queue.c net: Rename ifq_idx to rxq_idx in netif_mp_* helpers 2026-04-12 09:12:07 -07:00
netevent.c
netmem_priv.h mm: introduce a new page type for page pool in page type 2026-04-05 13:53:19 -07:00
netpoll.c netpoll: fix IPv6 local-address corruption 2026-04-27 19:16:18 -07:00
netprio_cgroup.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
of_net.c
page_pool.c page_pool: fix memory-provider leak in page_pool_create_percpu() error path 2026-04-29 19:11:49 -07:00
page_pool_priv.h
page_pool_user.c page_pool: store detach_time as ktime_t to avoid false-negatives 2026-03-10 19:03:34 -07:00
pktgen.c kernel.h: drop hex.h and update all hex.h users 2026-01-20 19:44:19 -08:00
ptp_classifier.c
rtnetlink.c net: introduce ndo_set_rx_mode_async and netdev_rx_mode_work 2026-04-21 12:50:03 +02:00
scm.c net: use ktime_t in struct scm_timestamping_internal 2026-03-04 17:53:34 -08:00
secure_seq.c tcp: secure_seq: add back ports to TS offset 2026-03-04 17:44:35 -08:00
selftests.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
skb_fault_injection.c
skbuff.c net: add noinline __init __no_profile to skb_extensions_init() for GCOV compatibility 2026-04-12 15:29:02 -07:00
skmsg.c bpf: sockmap: Fix use-after-free of sk->sk_socket in sk_psock_verdict_data_ready(). 2026-04-01 18:54:04 -07:00
sock.c tcp: update window_clamp when SO_RCVBUF is set 2026-04-13 15:32:35 +02:00
sock_destructor.h
sock_diag.c net: Add SPDX ids to some source files 2026-03-09 18:32:45 -07:00
sock_map.c bpf, sockmap: Annotate af_unix sock:: Sk_state data-races 2026-04-15 17:22:42 -07:00
sock_reuseport.c treewide: Replace kmalloc with kmalloc_obj for non-scalar types 2026-02-21 01:02:28 -08:00
stream.c net: stream: add description for sk_stream_write_space() 2025-07-18 16:57:21 -07:00
sysctl_net_core.c net: add skb_defer_disable_key static key 2026-03-12 19:25:33 -07:00
timestamping.c
tso.c net: tso: Introduce tso_dma_map and helpers 2026-04-12 10:54:31 -07:00
utils.c kernel.h: drop hex.h and update all hex.h users 2026-01-20 19:44:19 -08:00
xdp.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00