* [PATCH net v1 0/4] net: devmem: fix RX and TX binding teardown on device unregistration
@ 2026-10-10 2:55 Mina Almasry
2026-10-10 2:55 ` [PATCH net v1 1/4] net: devmem: unmap dma_buf synchronously on queue uninstall Mina Almasry
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Mina Almasry @ 2026-10-10 2:55 UTC (permalink / raw)
To: Jakub Kicinski, Mina Almasry, David Wei, Pavel Begunkov,
Taehee Yoo, Stanislav Fomichev, Paolo Abeni, Kaiyuan Zhang,
Bobby Eshleman, netdev, linux-kernel, linux-kselftest,
linux-media, dri-devel
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Simon Horman,
Shuah Khan, Sumit Semwal, Christian König, Daniel Borkmann,
Nikolay Aleksandrov, Tariq Toukan, Kaifeng Wang
Fix two device-unregistration lifecycle bugs in devmem TCP bindings and
add netdevsim support plus selftests covering both RX and TX device
unregistration:
1. net: devmem: unmap dma_buf synchronously on queue uninstall
Synchronously unmap and detach binding->attachment under binding->lock
when the last RX queue is uninstalled in mp_dmabuf_devmem_uninstall(),
preventing slab-use-after-free in dma_unmap_sg_attrs() when the netlink
socket closes after dma_dev is freed.
2. net: devmem: detach TX bindings on NETDEV_UNREGISTER
Add net_devmem_dev_unregister() on NETDEV_UNREGISTER to fully detach and
unmap TX bindings when binding->dev unregisters, or clear binding->vdev
alone when only a virtual device unregisters while binding->dev lives.
3. netdevsim: support devmem RX and TX bindings
Enable PP_FLAG_DMA_MAP | PP_FLAG_ALLOW_UNREADABLE_NETMEM, 64-bit DMA mask
on nsim_bus_dev, and NETMEM_TX_DMA on netdevsim so devmem RX/TX bindings
can be exercised in software selftests.
4. selftests: net: add devmem RX and TX netdev unregister tests
Add devmem_bind_rx_unregister_check and devmem_bind_tx_unregister_check
to tools/testing/selftests/net/nl_netdev.py.
Cc: Tariq Toukan <tariqt@nvidia.com>
Cc: Kaifeng Wang <kaifengw@google.com>
Mina Almasry (4):
net: devmem: unmap dma_buf synchronously on queue uninstall
net: devmem: detach TX bindings on NETDEV_UNREGISTER
netdevsim: support devmem RX and TX bindings
selftests: net: add devmem RX and TX netdev unregister tests
drivers/net/netdevsim/bus.c | 1 +
drivers/net/netdevsim/netdev.c | 21 +++--
net/core/devmem.c | 68 +++++++++++++-
net/core/devmem.h | 5 ++
net/core/netdev-genl.c | 1 +
tools/testing/selftests/net/nl_netdev.py | 108 ++++++++++++++++++++++-
6 files changed, 192 insertions(+), 12 deletions(-)
base-commit: af32da41b0327b9c6a37856ba82b6760d6c8d10e
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net v1 1/4] net: devmem: unmap dma_buf synchronously on queue uninstall
2026-10-10 2:55 [PATCH net v1 0/4] net: devmem: fix RX and TX binding teardown on device unregistration Mina Almasry
@ 2026-10-10 2:55 ` Mina Almasry
2026-10-10 2:55 ` [PATCH net v1 2/4] net: devmem: detach TX bindings on NETDEV_UNREGISTER Mina Almasry
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Mina Almasry @ 2026-10-10 2:55 UTC (permalink / raw)
To: Jakub Kicinski, Mina Almasry, David Wei, Pavel Begunkov,
Taehee Yoo, Stanislav Fomichev, Paolo Abeni, Kaiyuan Zhang,
Bobby Eshleman, netdev, linux-kernel, linux-kselftest,
linux-media, dri-devel
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Simon Horman,
Shuah Khan, Sumit Semwal, Christian König, Daniel Borkmann,
Nikolay Aleksandrov, Tariq Toukan, Kaifeng Wang
When a bound net_device is unregistered while userspace still holds a
netlink or TCP socket reference on a devmem binding,
mp_dmabuf_devmem_uninstall() clears binding->dev to NULL so
netdev_nl_sock_priv_destroy() will not touch the unregistered
net_device, but leaves the dma_buf attachment mapped until
__net_devmem_dmabuf_binding_free() runs later on socket close.
Because dma_buf_attach() does not take a reference on dma_dev, device
removal frees dma_dev while the attachment is still mapped. Closing the
netlink socket afterwards triggers a slab use-after-free in
dma_unmap_sg_attrs():
BUG: KASAN: slab-use-after-free in dma_unmap_sg_attrs+0x76/0x2b0
Read of size 8 at addr ffff88810fae64b0 by task kworker/3:1/53
Workqueue: events __net_devmem_dmabuf_binding_free
Call Trace:
dma_unmap_sg_attrs+0x76/0x2b0
unmap_udmabuf+0x8e/0x100
dma_buf_unmap_attachment+0x145/0x330
dma_buf_unmap_attachment_unlocked+0x96/0x130
__net_devmem_dmabuf_binding_free+0x156/0x2e0
Freed by task 9:
kfree+0x1b8/0x550
nsim_bus_dev_release+0xe/0x60
device_release+0xcf/0x250
Add net_devmem_dmabuf_binding_unmap() serialized under binding->lock
and null out binding->sgt and binding->attachment after unmapping so
unmapping is idempotent across queue uninstall and deferred binding
destruction. Call it synchronously when the last bound RX queue is
uninstalled in mp_dmabuf_devmem_uninstall().
Fixes: f8350a4358fc ("net: page_pool: add a mp hook to unregister_netdevice*")
Fixes: 0afc44d8cdf6 ("net: devmem: fix kernel panic when netlink socket close after module unload")
Cc: Taehee Yoo <ap420073@gmail.com>
Cc: Stanislav Fomichev <sdf@fomichev.me>
Cc: Tariq Toukan <tariqt@nvidia.com>
Cc: Kaifeng Wang <kaifengw@google.com>
Signed-off-by: Mina Almasry <almasrymina@google.com>
---
net/core/devmem.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/net/core/devmem.c b/net/core/devmem.c
index f4d60654ce7fd..5e4070b82df44 100644
--- a/net/core/devmem.c
+++ b/net/core/devmem.c
@@ -58,6 +58,21 @@ static void net_devmem_dmabuf_binding_release(struct percpu_ref *ref)
schedule_work(&binding->unbind_w);
}
+static void
+net_devmem_dmabuf_binding_unmap(struct net_devmem_dmabuf_binding *binding)
+{
+ lockdep_assert_held(&binding->lock);
+
+ if (!binding->sgt)
+ return;
+
+ dma_buf_unmap_attachment_unlocked(binding->attachment, binding->sgt,
+ binding->direction);
+ dma_buf_detach(binding->dmabuf, binding->attachment);
+ binding->sgt = NULL;
+ binding->attachment = NULL;
+}
+
void __net_devmem_dmabuf_binding_free(struct work_struct *wq)
{
struct net_devmem_dmabuf_binding *binding = container_of(wq, typeof(*binding), unbind_w);
@@ -74,9 +89,10 @@ void __net_devmem_dmabuf_binding_free(struct work_struct *wq)
size, avail))
gen_pool_destroy(binding->chunk_pool);
- dma_buf_unmap_attachment_unlocked(binding->attachment, binding->sgt,
- binding->direction);
- dma_buf_detach(binding->dmabuf, binding->attachment);
+ mutex_lock(&binding->lock);
+ net_devmem_dmabuf_binding_unmap(binding);
+ mutex_unlock(&binding->lock);
+
dma_buf_put(binding->dmabuf);
xa_destroy(&binding->bound_rxqs);
percpu_ref_exit(&binding->ref);
@@ -535,6 +551,7 @@ static void mp_dmabuf_devmem_uninstall(void *mp_priv,
mutex_lock(&binding->lock);
ASSERT_EXCLUSIVE_WRITER(binding->dev);
WRITE_ONCE(binding->dev, NULL);
+ net_devmem_dmabuf_binding_unmap(binding);
mutex_unlock(&binding->lock);
}
break;
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net v1 2/4] net: devmem: detach TX bindings on NETDEV_UNREGISTER
2026-10-10 2:55 [PATCH net v1 0/4] net: devmem: fix RX and TX binding teardown on device unregistration Mina Almasry
2026-10-10 2:55 ` [PATCH net v1 1/4] net: devmem: unmap dma_buf synchronously on queue uninstall Mina Almasry
@ 2026-10-10 2:55 ` Mina Almasry
2026-10-10 2:55 ` [PATCH net v1 3/4] netdevsim: support devmem RX and TX bindings Mina Almasry
2026-10-10 2:55 ` [PATCH net v1 4/4] selftests: net: add devmem RX and TX netdev unregister tests Mina Almasry
3 siblings, 0 replies; 5+ messages in thread
From: Mina Almasry @ 2026-10-10 2:55 UTC (permalink / raw)
To: Jakub Kicinski, Mina Almasry, David Wei, Pavel Begunkov,
Taehee Yoo, Stanislav Fomichev, Paolo Abeni, Kaiyuan Zhang,
Bobby Eshleman, netdev, linux-kernel, linux-kselftest,
linux-media, dri-devel
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Simon Horman,
Shuah Khan, Sumit Semwal, Christian König, Daniel Borkmann,
Nikolay Aleksandrov, Tariq Toukan, Kaifeng Wang
TX devmem bindings (NETDEV_CMD_BIND_TX) have no bound RX queues, so
mp_dmabuf_devmem_uninstall() never runs when binding->dev or
binding->vdev unregisters. As a result, binding->dev and binding->vdev
dangle pointing to freed struct net_device memory, and the dma_buf
remains attached and mapped after device removal.
Closing the netlink socket after netdev unregistration dereferences the
freed struct net_device in netdev_nl_sock_priv_destroy():
BUG: unable to handle page fault for address: ffff88824ca9b000
Oops: Oops: 0000 [#1] SMP KASAN NOPTI
RIP: 0010:netdev_nl_sock_priv_destroy+0xbd/0x1e0
Call Trace:
genl_release+0xf5/0x190
netlink_release+0xd01/0x18d0
__sock_release+0xb0/0x270
sock_close+0x18/0x20
Add net_devmem_dev_unregister() called on NETDEV_UNREGISTER:
- When binding->dev (the physical DMA-capable device) unregisters,
erase the binding ID, clear both binding->dev and binding->vdev, wait
for in-flight RCU/TX readers via synchronize_net(), and unmap the
dma_buf under binding->lock.
- When only binding->vdev (virtual device) unregisters while
binding->dev lives, only clear binding->vdev so no new TX sends match
the virtual device while allowing in-flight TX packets on binding->dev
to finish DMA safely.
Fixes: bd61848900bf ("net: devmem: Implement TX path")
Fixes: 1abe839b34ae ("net: devmem: support TX over NETMEM_TX_NO_DMA devices")
Cc: Kaiyuan Zhang <kaiyuanz@google.com>
Cc: Stanislav Fomichev <sdf@fomichev.me>
Cc: Bobby Eshleman <bobbyeshleman@meta.com>
Cc: Tariq Toukan <tariqt@nvidia.com>
Cc: Kaifeng Wang <kaifengw@google.com>
Signed-off-by: Mina Almasry <almasrymina@google.com>
---
net/core/devmem.c | 45 ++++++++++++++++++++++++++++++++++++++++++
net/core/devmem.h | 5 +++++
net/core/netdev-genl.c | 1 +
3 files changed, 51 insertions(+)
diff --git a/net/core/devmem.c b/net/core/devmem.c
index 5e4070b82df44..da7b3e8abaa13 100644
--- a/net/core/devmem.c
+++ b/net/core/devmem.c
@@ -169,6 +169,51 @@ void net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding)
percpu_ref_kill(&binding->ref);
}
+void net_devmem_dev_unregister(struct net_device *dev)
+{
+ struct net_devmem_dmabuf_binding *binding;
+ unsigned long xa_idx;
+
+ rcu_read_lock();
+ xa_for_each(&net_devmem_dmabuf_bindings, xa_idx, binding) {
+ if (!percpu_ref_tryget(&binding->ref))
+ continue;
+ rcu_read_unlock();
+
+ if (xa_empty(&binding->bound_rxqs)) {
+ if (READ_ONCE(binding->dev) == dev) {
+ xa_erase(&net_devmem_dmabuf_bindings,
+ binding->id);
+
+ mutex_lock(&binding->lock);
+ WRITE_ONCE(binding->dev, NULL);
+ WRITE_ONCE(binding->vdev, NULL);
+ mutex_unlock(&binding->lock);
+
+ /* Ensure no tx net_devmem_lookup_dmabuf() or
+ * validate_xmit_unreadable_skb() are in flight
+ * after detach.
+ */
+ synchronize_net();
+
+ mutex_lock(&binding->lock);
+ net_devmem_dmabuf_binding_unmap(binding);
+ mutex_unlock(&binding->lock);
+ } else if (READ_ONCE(binding->vdev) == dev) {
+ mutex_lock(&binding->lock);
+ WRITE_ONCE(binding->vdev, NULL);
+ mutex_unlock(&binding->lock);
+
+ synchronize_net();
+ }
+ }
+
+ net_devmem_dmabuf_binding_put(binding);
+ rcu_read_lock();
+ }
+ rcu_read_unlock();
+}
+
int net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
struct net_devmem_dmabuf_binding *binding,
struct netlink_ext_ack *extack)
diff --git a/net/core/devmem.h b/net/core/devmem.h
index 4a293a7d1149c..b572013d602c7 100644
--- a/net/core/devmem.h
+++ b/net/core/devmem.h
@@ -100,6 +100,7 @@ net_devmem_bind_dmabuf(struct net_device *dev, void *vdev,
struct netlink_ext_ack *extack);
struct net_devmem_dmabuf_binding *net_devmem_lookup_dmabuf(u32 id);
void net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding);
+void net_devmem_dev_unregister(struct net_device *dev);
int net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
struct net_devmem_dmabuf_binding *binding,
struct netlink_ext_ack *extack);
@@ -196,6 +197,10 @@ net_devmem_unbind_dmabuf(struct net_devmem_dmabuf_binding *binding)
{
}
+static inline void net_devmem_dev_unregister(struct net_device *dev)
+{
+}
+
static inline int
net_devmem_bind_dmabuf_to_queue(struct net_device *dev, u32 rxq_idx,
struct net_devmem_dmabuf_binding *binding,
diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index 33b9f4eb9565a..5bfcd513fb0e8 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -1487,6 +1487,7 @@ static int netdev_genl_netdevice_event(struct notifier_block *nb,
netdev_unlock_full_to_ops(netdev);
break;
case NETDEV_UNREGISTER:
+ net_devmem_dev_unregister(netdev);
netdev_lock(netdev);
netdev_genl_dev_notify(netdev, NETDEV_CMD_DEV_DEL_NTF);
netdev_unlock(netdev);
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net v1 3/4] netdevsim: support devmem RX and TX bindings
2026-10-10 2:55 [PATCH net v1 0/4] net: devmem: fix RX and TX binding teardown on device unregistration Mina Almasry
2026-10-10 2:55 ` [PATCH net v1 1/4] net: devmem: unmap dma_buf synchronously on queue uninstall Mina Almasry
2026-10-10 2:55 ` [PATCH net v1 2/4] net: devmem: detach TX bindings on NETDEV_UNREGISTER Mina Almasry
@ 2026-10-10 2:55 ` Mina Almasry
2026-10-10 2:55 ` [PATCH net v1 4/4] selftests: net: add devmem RX and TX netdev unregister tests Mina Almasry
3 siblings, 0 replies; 5+ messages in thread
From: Mina Almasry @ 2026-10-10 2:55 UTC (permalink / raw)
To: Jakub Kicinski, Mina Almasry, David Wei, Pavel Begunkov,
Taehee Yoo, Stanislav Fomichev, Paolo Abeni, Kaiyuan Zhang,
Bobby Eshleman, netdev, linux-kernel, linux-kselftest,
linux-media, dri-devel
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Simon Horman,
Shuah Khan, Sumit Semwal, Christian König, Daniel Borkmann,
Nikolay Aleksandrov, Tariq Toukan, Kaifeng Wang
Set a 64-bit DMA mask on nsim_bus_dev, enable NETMEM_TX_DMA on the
netdevsim net_device, and configure page_pool instances with
PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV | PP_FLAG_ALLOW_UNREADABLE_NETMEM
and queue_idx so devmem bind-rx and bind-tx netlink operations can be
tested against netdevsim in software selftests.
Cc: Tariq Toukan <tariqt@nvidia.com>
Cc: Kaifeng Wang <kaifengw@google.com>
Signed-off-by: Mina Almasry <almasrymina@google.com>
---
drivers/net/netdevsim/bus.c | 1 +
drivers/net/netdevsim/netdev.c | 21 +++++++++++++++------
2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c
index 5c55c308487b4..f87f5e037b6fb 100644
--- a/drivers/net/netdevsim/bus.c
+++ b/drivers/net/netdevsim/bus.c
@@ -462,6 +462,7 @@ nsim_bus_dev_new(unsigned int id, unsigned int port_count, unsigned int num_queu
nsim_bus_dev->port_count = port_count;
nsim_bus_dev->num_queues = num_queues;
nsim_bus_dev->initial_net = current->nsproxy->net_ns;
+ dma_coerce_mask_and_coherent(&nsim_bus_dev->dev, DMA_BIT_MASK(64));
/* Disallow using nsim_bus_dev */
smp_store_release(&nsim_bus_dev->init, false);
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index b4a99f3ceac60..4415dc01c610b 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -414,16 +414,22 @@ static int nsim_poll(struct napi_struct *napi, int budget)
return done;
}
-static int nsim_create_page_pool(struct page_pool **p, struct napi_struct *napi)
+static int nsim_create_page_pool(struct net_device *dev, struct page_pool **p,
+ struct napi_struct *napi, int idx)
{
+ struct netdevsim *ns = netdev_priv(dev);
struct page_pool_params params = {
.order = 0,
.pool_size = NSIM_RING_SIZE,
+ .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV |
+ PP_FLAG_ALLOW_UNREADABLE_NETMEM,
+ .max_len = PAGE_SIZE,
.nid = NUMA_NO_NODE,
- .dev = &napi->dev->dev,
+ .dev = &ns->nsim_bus_dev->dev,
.napi = napi,
.dma_dir = DMA_BIDIRECTIONAL,
- .netdev = napi->dev,
+ .netdev = dev,
+ .queue_idx = idx,
};
struct page_pool *pool;
@@ -450,7 +456,7 @@ static int nsim_init_napi(struct netdevsim *ns)
for (i = 0; i < dev->num_rx_queues; i++) {
rq = ns->rq[i];
- err = nsim_create_page_pool(&rq->page_pool, &rq->napi);
+ err = nsim_create_page_pool(dev, &rq->page_pool, &rq->napi, i);
if (err)
goto err_pp_destroy;
}
@@ -762,14 +768,16 @@ nsim_queue_mem_alloc(struct net_device *dev,
if (ns->rq_reset_mode == 1) {
if (!netif_running(ns->netdev))
return -ENETDOWN;
- return nsim_create_page_pool(&qmem->pp, &ns->rq[idx]->napi);
+ return nsim_create_page_pool(dev, &qmem->pp,
+ &ns->rq[idx]->napi, idx);
}
qmem->rq = nsim_queue_alloc();
if (!qmem->rq)
return -ENOMEM;
- err = nsim_create_page_pool(&qmem->rq->page_pool, &qmem->rq->napi);
+ err = nsim_create_page_pool(dev, &qmem->rq->page_pool, &qmem->rq->napi,
+ idx);
if (err)
goto err_free;
@@ -1051,6 +1059,7 @@ static int nsim_init_netdevsim(struct netdevsim *ns)
ns->netdev->netdev_ops = &nsim_netdev_ops;
ns->netdev->stat_ops = &nsim_stat_ops;
ns->netdev->queue_mgmt_ops = &nsim_queue_mgmt_ops;
+ ns->netdev->netmem_tx = NETMEM_TX_DMA;
netdev_lockdep_set_classes(ns->netdev);
err = nsim_udp_tunnels_info_create(ns->nsim_dev, ns->netdev);
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net v1 4/4] selftests: net: add devmem RX and TX netdev unregister tests
2026-10-10 2:55 [PATCH net v1 0/4] net: devmem: fix RX and TX binding teardown on device unregistration Mina Almasry
` (2 preceding siblings ...)
2026-10-10 2:55 ` [PATCH net v1 3/4] netdevsim: support devmem RX and TX bindings Mina Almasry
@ 2026-10-10 2:55 ` Mina Almasry
3 siblings, 0 replies; 5+ messages in thread
From: Mina Almasry @ 2026-10-10 2:55 UTC (permalink / raw)
To: Jakub Kicinski, Mina Almasry, David Wei, Pavel Begunkov,
Taehee Yoo, Stanislav Fomichev, Paolo Abeni, Kaiyuan Zhang,
Bobby Eshleman, netdev, linux-kernel, linux-kselftest,
linux-media, dri-devel
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Simon Horman,
Shuah Khan, Sumit Semwal, Christian König, Daniel Borkmann,
Nikolay Aleksandrov, Tariq Toukan, Kaifeng Wang
Add devmem_bind_rx_unregister_check and devmem_bind_tx_unregister_check
to nl_netdev.py to verify that unregistering a netdevsim device while a
netlink socket holds an active RX or TX devmem binding synchronously
detaches the dma_buf attachment and cleanly closes the netlink socket
without use-after-free or page faults.
Cc: Tariq Toukan <tariqt@nvidia.com>
Cc: Kaifeng Wang <kaifengw@google.com>
Signed-off-by: Mina Almasry <almasrymina@google.com>
---
tools/testing/selftests/net/nl_netdev.py | 108 ++++++++++++++++++++++-
1 file changed, 105 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/net/nl_netdev.py b/tools/testing/selftests/net/nl_netdev.py
index ceb44c8e1fec5..bad230ee9dcd2 100755
--- a/tools/testing/selftests/net/nl_netdev.py
+++ b/tools/testing/selftests/net/nl_netdev.py
@@ -6,10 +6,14 @@ Tests for the netdev netlink family.
"""
import errno
+import fcntl
+import mmap
+import os
+import struct
from os import system
-from lib.py import ksft_run, ksft_exit
+from lib.py import ksft_run, ksft_exit, KsftSkipEx
from lib.py import ksft_eq, ksft_ge, ksft_ne, ksft_raises, ksft_busy_wait
-from lib.py import NetdevFamily, NetdevSimDev, NlError, defer, ip
+from lib.py import EthtoolFamily, NetdevFamily, NetdevSimDev, NlError, defer, ip
def empty_check(nf) -> None:
@@ -366,6 +370,102 @@ def page_pool_stats_ifindex_check(nf) -> None:
ksft_eq(cm.exception.nl_msg.extack['bad-attr'], '.info.id')
+def _create_udmabuf(num_pages=64) -> int:
+ """Create a sealed memfd-backed udmabuf fd for devmem tests."""
+ if not os.path.exists("/dev/udmabuf"):
+ raise KsftSkipEx("/dev/udmabuf is not available")
+
+ size = num_pages * mmap.PAGESIZE
+ memfd = os.memfd_create("devmem-ksft", os.MFD_ALLOW_SEALING)
+ os.ftruncate(memfd, size)
+ fcntl.fcntl(memfd, 1033, 0x0002) # F_ADD_SEALS, F_SEAL_SHRINK
+ devfd = os.open("/dev/udmabuf", os.O_RDWR)
+ req = bytearray(struct.pack("IIQQ", memfd, 0, 0, size))
+ dmabuf_fd = fcntl.ioctl(devfd, 0x40187542, req) # UDMABUF_CREATE
+ os.close(devfd)
+ os.close(memfd)
+ return dmabuf_fd
+
+
+def _dmabuf_attached_devs():
+ """Return attached device names from debugfs dma_buf/bufinfo if available."""
+ path = "/sys/kernel/debug/dma_buf/bufinfo"
+ if not os.path.exists(path):
+ return None
+ with open(path, "r", encoding="utf-8") as f:
+ text = f.read()
+ attached = []
+ in_attached = False
+ for line in text.splitlines():
+ if line.strip() == "Attached Devices:":
+ in_attached = True
+ continue
+ if in_attached:
+ if line.startswith("\t") and line.strip():
+ attached.append(line.strip())
+ else:
+ in_attached = False
+ return attached
+
+
+def devmem_bind_rx_unregister_check(_nf) -> None:
+ """Verify RX devmem bindings detach dma_buf synchronously on netdev unregister."""
+ dmabuf_fd = _create_udmabuf()
+ nf_priv = NetdevFamily()
+ ef = EthtoolFamily()
+ nsimdev = NetdevSimDev(queue_count=2)
+ nsim = nsimdev.nsims[0]
+
+ ip(f"link set dev {nsim.ifname} up")
+ ef.rings_set({"header": {"dev-index": nsim.ifindex},
+ "tcp-data-split": "enabled"})
+ nf_priv.bind_rx({
+ "ifindex": nsim.ifindex,
+ "fd": dmabuf_fd,
+ "queues": [{"id": 1, "type": "rx"}],
+ })
+
+ attached = _dmabuf_attached_devs()
+ if attached is not None:
+ ksft_ge(len(attached), 1)
+
+ nsimdev.remove()
+
+ attached = _dmabuf_attached_devs()
+ if attached is not None:
+ ksft_eq(len(attached), 0)
+
+ del nf_priv
+ os.close(dmabuf_fd)
+
+
+def devmem_bind_tx_unregister_check(_nf) -> None:
+ """Verify TX devmem bindings detach cleanly on netdev unregister without UAF."""
+ dmabuf_fd = _create_udmabuf()
+ nf_priv = NetdevFamily()
+ nsimdev = NetdevSimDev(queue_count=2)
+ nsim = nsimdev.nsims[0]
+
+ ip(f"link set dev {nsim.ifname} up")
+ nf_priv.bind_tx({
+ "ifindex": nsim.ifindex,
+ "fd": dmabuf_fd,
+ })
+
+ attached = _dmabuf_attached_devs()
+ if attached is not None:
+ ksft_ge(len(attached), 1)
+
+ nsimdev.remove()
+
+ attached = _dmabuf_attached_devs()
+ if attached is not None:
+ ksft_eq(len(attached), 0)
+
+ del nf_priv
+ os.close(dmabuf_fd)
+
+
def main() -> None:
""" Ksft boiler plate main """
nf = NetdevFamily()
@@ -379,7 +479,9 @@ def main() -> None:
page_pool_check,
page_pool_dump_ifindex,
page_pool_ifindex_leak_check,
- page_pool_stats_ifindex_check
+ page_pool_stats_ifindex_check,
+ devmem_bind_rx_unregister_check,
+ devmem_bind_tx_unregister_check
],
args=(nf, ))
ksft_exit()
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-10 2:55 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-10 2:55 [PATCH net v1 0/4] net: devmem: fix RX and TX binding teardown on device unregistration Mina Almasry
2026-10-10 2:55 ` [PATCH net v1 1/4] net: devmem: unmap dma_buf synchronously on queue uninstall Mina Almasry
2026-10-10 2:55 ` [PATCH net v1 2/4] net: devmem: detach TX bindings on NETDEV_UNREGISTER Mina Almasry
2026-10-10 2:55 ` [PATCH net v1 3/4] netdevsim: support devmem RX and TX bindings Mina Almasry
2026-10-10 2:55 ` [PATCH net v1 4/4] selftests: net: add devmem RX and TX netdev unregister tests Mina Almasry
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®