* [PATCH rdma-next 01/13] RDMA/core: Pass the net namespace to the device name lookups
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 02/13] RDMA/core: Handle device name conflicts when changing net namespace Jiri Pirko
` (11 subsequent siblings)
12 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Prepare for per-netns RDMA device names by passing the target net
namespace through the name lookup and allocation helpers. Keep current
global uniqueness behaviour.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/device.c | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index b8193e077a74..de610f52c9b2 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -351,7 +351,8 @@ void ib_device_put(struct ib_device *device)
}
EXPORT_SYMBOL(ib_device_put);
-static struct ib_device *__ib_device_get_by_name(const char *name)
+static struct ib_device *__ib_device_get_by_name(const char *name,
+ const struct net *net)
{
struct ib_device *device;
unsigned long index;
@@ -395,7 +396,7 @@ int ib_device_rename(struct ib_device *ibdev, const char *name)
return 0;
}
- if (__ib_device_get_by_name(name)) {
+ if (__ib_device_get_by_name(name, rdma_dev_net(ibdev))) {
up_write(&devices_rwsem);
return -EEXIST;
}
@@ -435,7 +436,8 @@ int ib_device_set_dim(struct ib_device *ibdev, u8 use_dim)
return 0;
}
-static int alloc_name(struct ib_device *ibdev, const char *name)
+/* Pick a free index for the '%d' style @name pattern. */
+static int alloc_name_id(struct net *net, const char *name)
{
struct ib_device *device;
unsigned long index;
@@ -462,15 +464,22 @@ static int alloc_name(struct ib_device *ibdev, const char *name)
}
rc = ida_alloc(&inuse, GFP_KERNEL);
- if (rc < 0)
- goto out;
-
- rc = dev_set_name(&ibdev->dev, name, rc);
out:
ida_destroy(&inuse);
return rc;
}
+static int alloc_name(struct ib_device *ibdev, const char *name)
+{
+ int id;
+
+ id = alloc_name_id(rdma_dev_net(ibdev), name);
+ if (id < 0)
+ return id;
+
+ return dev_set_name(&ibdev->dev, name, id);
+}
+
static void ib_device_release(struct device *device)
{
struct ib_device *dev = container_of(device, struct ib_device, dev);
@@ -1223,7 +1232,8 @@ static int assign_name(struct ib_device *device, const char *name)
if (ret)
goto out;
- if (__ib_device_get_by_name(dev_name(&device->dev))) {
+ if (__ib_device_get_by_name(dev_name(&device->dev),
+ rdma_dev_net(device))) {
ret = -ENFILE;
goto out;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH rdma-next 02/13] RDMA/core: Handle device name conflicts when changing net namespace
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 01/13] RDMA/core: Pass the net namespace to the device name lookups Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-10 9:56 ` sashiko-bot
2026-07-09 9:55 ` [PATCH rdma-next 03/13] RDMA/core: Support renaming a device when changing its " Jiri Pirko
` (10 subsequent siblings)
12 siblings, 1 reply; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Prepare namespace moves for per-netns names. Check user-initiated moves for
destination-name conflicts before disabling the device, keep same-netns
moves as no-ops, and make teardown moves detach from the exiting namespace
even if fallback naming fails.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/device.c | 155 ++++++++++++++++++++++++++-----
drivers/infiniband/core/nldev.c | 3 +
2 files changed, 137 insertions(+), 21 deletions(-)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index de610f52c9b2..8d169658e312 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -268,7 +268,7 @@ static struct notifier_block ibdev_lsm_nb = {
};
static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
- struct net *net);
+ struct net *net, const char *fallback_pattern);
/* Pointer to the RCU head at the start of the ib_port_data array */
struct ib_port_data_rcu {
@@ -437,7 +437,8 @@ int ib_device_set_dim(struct ib_device *ibdev, u8 use_dim)
}
/* Pick a free index for the '%d' style @name pattern. */
-static int alloc_name_id(struct net *net, const char *name)
+static int __alloc_name_id(struct net *net, const char *name,
+ const struct ib_device *skip)
{
struct ib_device *device;
unsigned long index;
@@ -450,6 +451,8 @@ static int alloc_name_id(struct net *net, const char *name)
xa_for_each (&devices, index, device) {
char buf[IB_DEVICE_NAME_MAX];
+ if (device == skip)
+ continue;
if (sscanf(dev_name(&device->dev), name, &i) != 1)
continue;
if (i < 0 || i >= INT_MAX)
@@ -469,6 +472,11 @@ static int alloc_name_id(struct net *net, const char *name)
return rc;
}
+static int alloc_name_id(struct net *net, const char *name)
+{
+ return __alloc_name_id(net, name, NULL);
+}
+
static int alloc_name(struct ib_device *ibdev, const char *name)
{
int id;
@@ -1160,8 +1168,17 @@ static void rdma_dev_exit_net(struct net *net)
/*
* If the real device is in the NS then move it back to init.
+ * Provide a fallback pattern so a name conflict in init_net
+ * cannot make the teardown move fail.
*/
- rdma_dev_change_netns(dev, net, &init_net);
+ if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
+ ret = rdma_dev_change_netns(dev, net, &init_net,
+ "ibdev%d");
+ if (ret)
+ WARN(1,
+ "Failed to move RDMA device %s to init_net on netns exit: %d\n",
+ dev_name(&dev->dev), ret);
+ }
put_device(&dev->dev);
down_read(&devices_rwsem);
@@ -1680,14 +1697,71 @@ void ib_unregister_device_queued(struct ib_device *ib_dev)
}
EXPORT_SYMBOL(ib_unregister_device_queued);
+static bool rdma_dev_name_in_netns(struct ib_device *skip, struct net *net,
+ const char *name)
+{
+ struct ib_device *device;
+ unsigned long index;
+
+ lockdep_assert_held_write(&devices_rwsem);
+
+ xa_for_each(&devices, index, device)
+ if (device != skip &&
+ !strcmp(name, dev_name(&device->dev)))
+ return true;
+
+ return false;
+}
+
+/*
+ * Choose the name @device should use in net namespace @net: keep the current
+ * name when it is free, otherwise use a trusted '%d' @fallback_pattern
+ * (namespace teardown) to pick a free index. The caller must hold the write
+ * side of devices_rwsem.
+ */
+static int rdma_dev_pick_netns_name(struct ib_device *device, struct net *net,
+ const char *fallback_pattern,
+ char *buf, size_t buf_len,
+ const char **new_name)
+{
+ int id;
+
+ lockdep_assert_held_write(&devices_rwsem);
+
+ if (!rdma_dev_name_in_netns(device, net, dev_name(&device->dev))) {
+ *new_name = dev_name(&device->dev);
+ return 0;
+ }
+
+ if (!fallback_pattern)
+ return -EEXIST;
+
+ snprintf(buf, buf_len, "ibdev%u", device->index);
+ if (!rdma_dev_name_in_netns(device, net, buf)) {
+ *new_name = buf;
+ return 0;
+ }
+
+ id = __alloc_name_id(net, fallback_pattern, device);
+ if (id < 0)
+ return id;
+ snprintf(buf, buf_len, fallback_pattern, id);
+ *new_name = buf;
+ return 0;
+}
+
/*
* The caller must pass in a device that has the kref held and the refcount
* released. If the device is in cur_net and still registered then it is moved
* into net.
+ *
+ * Naming rules are handled by rdma_dev_pick_netns_name().
*/
static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
- struct net *net)
+ struct net *net, const char *fallback_pattern)
{
+ char buf[IB_DEVICE_NAME_MAX];
+ const char *new_name;
int ret2 = -EINVAL;
int ret;
@@ -1704,30 +1778,63 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
goto out;
}
+ if (!fallback_pattern) {
+ /*
+ * Reject a predictable name conflict before tearing anything
+ * down, so a doomed user move does not disable a live device.
+ */
+ down_write(&devices_rwsem);
+ ret = rdma_dev_pick_netns_name(device, net, fallback_pattern,
+ buf, sizeof(buf), &new_name);
+ up_write(&devices_rwsem);
+ if (ret)
+ goto out;
+ }
+
kobject_uevent(&device->dev.kobj, KOBJ_REMOVE);
disable_device(device);
/*
- * At this point no one can be using the device, so it is safe to
- * change the namespace.
+ * Recompute the destination name under the write side of devices_rwsem
+ * now that the device is disabled, closing races with a concurrent
+ * registration or rename, then publish the new namespace at the sysfs
+ * level.
*/
- write_pnet(&device->coredev.rdma_net, net);
+ down_write(&devices_rwsem);
+ ret = rdma_dev_pick_netns_name(device, net, fallback_pattern, buf,
+ sizeof(buf), &new_name);
+ if (ret) {
+ if (fallback_pattern) {
+ WARN(1,
+ "%s: failed to pick device name during namespace teardown: %d\n",
+ __func__, ret);
+ write_pnet(&device->coredev.rdma_net, net);
+ ret = 0;
+ }
+ goto rename_done;
+ }
- down_read(&devices_rwsem);
- /*
- * Currently rdma devices are system wide unique. So the device name
- * is guaranteed free in the new namespace. Publish the new namespace
- * at the sysfs level.
- */
- ret = device_rename(&device->dev, dev_name(&device->dev));
- up_read(&devices_rwsem);
+ write_pnet(&device->coredev.rdma_net, net);
+ ret = device_rename(&device->dev, new_name);
if (ret) {
- dev_warn(&device->dev,
- "%s: Couldn't rename device after namespace change\n",
- __func__);
- /* Try and put things back and re-enable the device */
- write_pnet(&device->coredev.rdma_net, cur_net);
+ if (fallback_pattern) {
+ WARN(1,
+ "%s: failed to rename device during namespace teardown: %d\n",
+ __func__, ret);
+ ret = 0;
+ } else {
+ dev_warn(&device->dev,
+ "%s: Couldn't rename device after namespace change\n",
+ __func__);
+ /* Try and put things back and re-enable the device */
+ write_pnet(&device->coredev.rdma_net, cur_net);
+ }
+ } else {
+ strscpy(device->name, dev_name(&device->dev),
+ IB_DEVICE_NAME_MAX);
}
+rename_done:
+ up_write(&devices_rwsem);
ret2 = enable_device_and_get(device);
if (ret2) {
@@ -1766,6 +1873,12 @@ int ib_device_set_netns_put(struct sk_buff *skb,
goto ns_err;
}
+ /* Moving a device to the namespace it already lives in is a no-op. */
+ if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
+ ret = 0;
+ goto ns_err;
+ }
+
/*
* All the ib_clients, including uverbs, are reset when the namespace is
* changed and this cannot be blocked waiting for userspace to do
@@ -1778,7 +1891,7 @@ int ib_device_set_netns_put(struct sk_buff *skb,
get_device(&dev->dev);
ib_device_put(dev);
- ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net);
+ ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net, NULL);
put_device(&dev->dev);
put_net(net);
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index f599c24b34e8..3a9ec43a16f1 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1195,6 +1195,9 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
err = ib_device_set_netns_put(skb, device, ns_fd);
+ if (err == -EEXIST)
+ NL_SET_ERR_MSG(extack,
+ "Device name already exists in the target net namespace");
goto put_done;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH rdma-next 02/13] RDMA/core: Handle device name conflicts when changing net namespace
2026-07-09 9:55 ` [PATCH rdma-next 02/13] RDMA/core: Handle device name conflicts when changing net namespace Jiri Pirko
@ 2026-07-10 9:56 ` sashiko-bot
0 siblings, 0 replies; 23+ messages in thread
From: sashiko-bot @ 2026-07-10 9:56 UTC (permalink / raw)
To: Jiri Pirko
Cc: Vasily Gorbik, linux-s390, mkoutny, Alexander Gordeev, tj,
Heiko Carstens, hannes
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] User-triggerable WARN() during concurrent RDMA device unregistration and netns exit, leading to DoS on panic_on_warn systems.
--
--- Patch [2]: [PATCH rdma-next 02/13] RDMA/core: Handle device name conflicts when changing net namespace ---
commit 05c3f87e2143d43f2f1e27d0f13e1b1f97f35bab
Author: Jiri Pirko <jiri@nvidia.com>
RDMA/core: Handle device name conflicts when changing net namespace
This commit prepares namespace moves for per-netns names by checking
user-initiated moves for destination-name conflicts before disabling the
device. It also ensures teardown moves detach from the exiting namespace
even if fallback naming fails.
> diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
> --- a/drivers/infiniband/core/device.c
> +++ b/drivers/infiniband/core/device.c
> @@ -1160,8 +1168,17 @@ static void rdma_dev_exit_net(struct net *net)
>
> /*
> * If the real device is in the NS then move it back to init.
> + * Provide a fallback pattern so a name conflict in init_net
> + * cannot make the teardown move fail.
> */
> - rdma_dev_change_netns(dev, net, &init_net);
> + if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
> + ret = rdma_dev_change_netns(dev, net, &init_net,
> + "ibdev%d");
> + if (ret)
> + WARN(1,
> + "Failed to move RDMA device %s to init_net on netns exit: %d\n",
> + dev_name(&dev->dev), ret);
[Severity: High]
Can this WARN(1) be triggered by a concurrent device unregistration?
Looking at rdma_dev_change_netns(), if a device is concurrently unregistered,
the refcount drops to 0 and the function legitimately returns -ENODEV:
drivers/infiniband/core/device.c:rdma_dev_change_netns() {
...
if (refcount_read(&device->refcount) == 0 ||
!net_eq(cur_net, read_pnet(&device->coredev.rdma_net))) {
ret = -ENODEV;
goto out;
}
...
}
If rdma_dev_exit_net() runs concurrently with device unregistration (e.g.,
module unload, PCI hotplug, or link deletion of a software RDMA device like
RXE), rdma_dev_change_netns() will return -ENODEV and trigger this warning.
Because an unprivileged user can acquire CAP_NET_ADMIN in a user namespace,
create an RXE device, and race netns deletion with device deletion, could
this be used to intentionally crash a host configured with panic_on_warn=1?
> + }
>
> put_device(&dev->dev);
> down_read(&devices_rwsem);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260709095532.855647-1-jiri@resnulli.us?part=2
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH rdma-next 03/13] RDMA/core: Support renaming a device when changing its net namespace
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 01/13] RDMA/core: Pass the net namespace to the device name lookups Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 02/13] RDMA/core: Handle device name conflicts when changing net namespace Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-10 9:56 ` sashiko-bot
2026-07-09 9:55 ` [PATCH rdma-next 04/13] RDMA/nldev: Report net namespace move errors through extack Jiri Pirko
` (9 subsequent siblings)
12 siblings, 1 reply; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Allow namespace moves to request a destination device name. Keep requested
names on the same literal-name path as the existing RDMA rename operation,
and keep teardown fallback naming on the trusted kernel-controlled path.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/core_priv.h | 2 +-
drivers/infiniband/core/device.c | 48 ++++++++++++++++++++---------
drivers/infiniband/core/nldev.c | 2 +-
3 files changed, 35 insertions(+), 17 deletions(-)
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 19104c542b27..3bd5bb7135a3 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -356,7 +356,7 @@ void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,
const struct attribute_group **groups);
int ib_device_set_netns_put(struct sk_buff *skb,
- struct ib_device *dev, u32 ns_fd);
+ struct ib_device *dev, u32 ns_fd, const char *name);
int rdma_nl_net_init(struct rdma_dev_net *rnet);
void rdma_nl_net_exit(struct rdma_dev_net *rnet);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 8d169658e312..191f05898bae 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -268,7 +268,8 @@ static struct notifier_block ibdev_lsm_nb = {
};
static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
- struct net *net, const char *fallback_pattern);
+ struct net *net, const char *requested_name,
+ const char *fallback_pattern);
/* Pointer to the RCU head at the start of the ib_port_data array */
struct ib_port_data_rcu {
@@ -1173,7 +1174,7 @@ static void rdma_dev_exit_net(struct net *net)
*/
if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
ret = rdma_dev_change_netns(dev, net, &init_net,
- "ibdev%d");
+ NULL, "ibdev%d");
if (ret)
WARN(1,
"Failed to move RDMA device %s to init_net on netns exit: %d\n",
@@ -1714,12 +1715,13 @@ static bool rdma_dev_name_in_netns(struct ib_device *skip, struct net *net,
}
/*
- * Choose the name @device should use in net namespace @net: keep the current
- * name when it is free, otherwise use a trusted '%d' @fallback_pattern
- * (namespace teardown) to pick a free index. The caller must hold the write
- * side of devices_rwsem.
+ * Choose the name @device should use in net namespace @net. @requested_name
+ * is used as a literal device name when set. Otherwise keep the current name
+ * when it is free, or use a trusted '%d' @fallback_pattern for teardown. The
+ * caller must hold the write side of devices_rwsem.
*/
static int rdma_dev_pick_netns_name(struct ib_device *device, struct net *net,
+ const char *requested_name,
const char *fallback_pattern,
char *buf, size_t buf_len,
const char **new_name)
@@ -1728,6 +1730,15 @@ static int rdma_dev_pick_netns_name(struct ib_device *device, struct net *net,
lockdep_assert_held_write(&devices_rwsem);
+ if (requested_name) {
+ if (!rdma_dev_name_in_netns(device, net, requested_name)) {
+ *new_name = requested_name;
+ return 0;
+ }
+
+ return -EEXIST;
+ }
+
if (!rdma_dev_name_in_netns(device, net, dev_name(&device->dev))) {
*new_name = dev_name(&device->dev);
return 0;
@@ -1758,7 +1769,8 @@ static int rdma_dev_pick_netns_name(struct ib_device *device, struct net *net,
* Naming rules are handled by rdma_dev_pick_netns_name().
*/
static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
- struct net *net, const char *fallback_pattern)
+ struct net *net, const char *requested_name,
+ const char *fallback_pattern)
{
char buf[IB_DEVICE_NAME_MAX];
const char *new_name;
@@ -1784,8 +1796,9 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
* down, so a doomed user move does not disable a live device.
*/
down_write(&devices_rwsem);
- ret = rdma_dev_pick_netns_name(device, net, fallback_pattern,
- buf, sizeof(buf), &new_name);
+ ret = rdma_dev_pick_netns_name(device, net, requested_name,
+ fallback_pattern, buf,
+ sizeof(buf), &new_name);
up_write(&devices_rwsem);
if (ret)
goto out;
@@ -1801,8 +1814,9 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
* level.
*/
down_write(&devices_rwsem);
- ret = rdma_dev_pick_netns_name(device, net, fallback_pattern, buf,
- sizeof(buf), &new_name);
+ ret = rdma_dev_pick_netns_name(device, net, requested_name,
+ fallback_pattern, buf, sizeof(buf),
+ &new_name);
if (ret) {
if (fallback_pattern) {
WARN(1,
@@ -1857,7 +1871,7 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
}
int ib_device_set_netns_put(struct sk_buff *skb,
- struct ib_device *dev, u32 ns_fd)
+ struct ib_device *dev, u32 ns_fd, const char *name)
{
struct net *net;
int ret;
@@ -1873,9 +1887,12 @@ int ib_device_set_netns_put(struct sk_buff *skb,
goto ns_err;
}
- /* Moving a device to the namespace it already lives in is a no-op. */
+ /*
+ * Moving a device to the namespace it already lives in is a no-op; a
+ * supplied name still renames it in place.
+ */
if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
- ret = 0;
+ ret = name ? ib_device_rename(dev, name) : 0;
goto ns_err;
}
@@ -1891,7 +1908,8 @@ int ib_device_set_netns_put(struct sk_buff *skb,
get_device(&dev->dev);
ib_device_put(dev);
- ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net, NULL);
+ ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net, name,
+ NULL);
put_device(&dev->dev);
put_net(net);
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 3a9ec43a16f1..3540cb0b9d4f 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1194,7 +1194,7 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
u32 ns_fd;
ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
- err = ib_device_set_netns_put(skb, device, ns_fd);
+ err = ib_device_set_netns_put(skb, device, ns_fd, NULL);
if (err == -EEXIST)
NL_SET_ERR_MSG(extack,
"Device name already exists in the target net namespace");
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH rdma-next 03/13] RDMA/core: Support renaming a device when changing its net namespace
2026-07-09 9:55 ` [PATCH rdma-next 03/13] RDMA/core: Support renaming a device when changing its " Jiri Pirko
@ 2026-07-10 9:56 ` sashiko-bot
0 siblings, 0 replies; 23+ messages in thread
From: sashiko-bot @ 2026-07-10 9:56 UTC (permalink / raw)
To: Jiri Pirko
Cc: mkoutny, Vasily Gorbik, hannes, tj, linux-s390, Heiko Carstens,
Alexander Gordeev
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The destination device name requested by userspace is ignored during a net namespace move because NULL is hardcoded in the netlink handler.
--
--- Patch [3]: [PATCH rdma-next 03/13] RDMA/core: Support renaming a device when changing its net namespace ---
commit 481a893ec5cd10a7f8be8c8de249d86cc283c470
Author: Jiri Pirko <jiri@nvidia.com>
RDMA/core: Support renaming a device when changing its net namespace
This patch updates the RDMA core to allow requesting a destination device
name when moving a device to a different network namespace. It modifies
ib_device_set_netns_put to take a requested name and implements the naming
rules during namespace teardown.
> diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
> index 3a9ec43a16f1a..3540cb0b9d4fb 100644
> --- a/drivers/infiniband/core/nldev.c
> +++ b/drivers/infiniband/core/nldev.c
> @@ -1194,7 +1194,7 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
> u32 ns_fd;
>
> ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
> - err = ib_device_set_netns_put(skb, device, ns_fd);
> + err = ib_device_set_netns_put(skb, device, ns_fd, NULL);
[Severity: Medium]
Does this hardcode NULL instead of extracting and passing the user-provided
device name?
The commit message mentions allowing namespace moves to request a destination
device name, but it appears ib_device_set_netns_put is always called with
NULL here.
How does this interact with the rename logic in nldev_set_doit? If a user
supplies both the RDMA_NLDEV_ATTR_DEV_NAME and RDMA_NLDEV_NET_NS_FD
attributes in the netlink command, will the code enter the rename logic first
and return, completely skipping the net namespace change instead of moving and
renaming the device?
> if (err == -EEXIST)
> NL_SET_ERR_MSG(extack,
> "Device name already exists in the target net namespace");
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260709095532.855647-1-jiri@resnulli.us?part=3
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH rdma-next 04/13] RDMA/nldev: Report net namespace move errors through extack
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (2 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 03/13] RDMA/core: Support renaming a device when changing its " Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 05/13] RDMA/nldev: Allow setting the device name while changing net namespace Jiri Pirko
` (8 subsequent siblings)
12 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Thread extack through the existing net namespace move helper and report the
main failure reasons from the core path. Keep the existing move UAPI shape
unchanged.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/core_priv.h | 3 ++-
drivers/infiniband/core/device.c | 24 ++++++++++++++++++++++--
drivers/infiniband/core/nldev.c | 6 ++----
3 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index 3bd5bb7135a3..aaf330b0d333 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -356,7 +356,8 @@ void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,
const struct attribute_group **groups);
int ib_device_set_netns_put(struct sk_buff *skb,
- struct ib_device *dev, u32 ns_fd, const char *name);
+ struct ib_device *dev, u32 ns_fd, const char *name,
+ struct netlink_ext_ack *extack);
int rdma_nl_net_init(struct rdma_dev_net *rnet);
void rdma_nl_net_exit(struct rdma_dev_net *rnet);
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 191f05898bae..2391bc7c8d23 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1871,18 +1871,22 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
}
int ib_device_set_netns_put(struct sk_buff *skb,
- struct ib_device *dev, u32 ns_fd, const char *name)
+ struct ib_device *dev, u32 ns_fd, const char *name,
+ struct netlink_ext_ack *extack)
{
struct net *net;
int ret;
net = get_net_ns_by_fd(ns_fd);
if (IS_ERR(net)) {
+ NL_SET_ERR_MSG(extack, "Invalid target net namespace fd");
ret = PTR_ERR(net);
goto net_err;
}
if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
+ NL_SET_ERR_MSG(extack,
+ "Missing CAP_NET_ADMIN in the target net namespace");
ret = -EPERM;
goto ns_err;
}
@@ -1893,6 +1897,10 @@ int ib_device_set_netns_put(struct sk_buff *skb,
*/
if (net_eq(net, read_pnet(&dev->coredev.rdma_net))) {
ret = name ? ib_device_rename(dev, name) : 0;
+
+ if (ret == -EEXIST)
+ NL_SET_ERR_MSG(extack,
+ "Device name already exists in the target net namespace");
goto ns_err;
}
@@ -1901,7 +1909,16 @@ int ib_device_set_netns_put(struct sk_buff *skb,
* changed and this cannot be blocked waiting for userspace to do
* something, so disassociation is mandatory.
*/
- if (!dev->ops.disassociate_ucontext || ib_devices_shared_netns) {
+ if (ib_devices_shared_netns) {
+ NL_SET_ERR_MSG(extack,
+ "Cannot change net namespace of RDMA device in shared netns mode");
+ ret = -EOPNOTSUPP;
+ goto ns_err;
+ }
+
+ if (!dev->ops.disassociate_ucontext) {
+ NL_SET_ERR_MSG(extack,
+ "Device does not support namespace changes (no disassociate support)");
ret = -EOPNOTSUPP;
goto ns_err;
}
@@ -1911,6 +1928,9 @@ int ib_device_set_netns_put(struct sk_buff *skb,
ret = rdma_dev_change_netns(dev, current->nsproxy->net_ns, net, name,
NULL);
put_device(&dev->dev);
+ if (ret == -EEXIST)
+ NL_SET_ERR_MSG(extack,
+ "Device name already exists in the target net namespace");
put_net(net);
return ret;
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 3540cb0b9d4f..5fd1ef2c5050 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1194,10 +1194,8 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
u32 ns_fd;
ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
- err = ib_device_set_netns_put(skb, device, ns_fd, NULL);
- if (err == -EEXIST)
- NL_SET_ERR_MSG(extack,
- "Device name already exists in the target net namespace");
+ err = ib_device_set_netns_put(skb, device, ns_fd, NULL,
+ extack);
goto put_done;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH rdma-next 05/13] RDMA/nldev: Allow setting the device name while changing net namespace
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (3 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 04/13] RDMA/nldev: Report net namespace move errors through extack Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 06/13] net/smc: Look up the pnetid ib device within the " Jiri Pirko
` (7 subsequent siblings)
12 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Accept RDMA_NLDEV_ATTR_DEV_NAME together with RDMA_NLDEV_NET_NS_FD so a
netlink move can rename the device in the destination namespace. Keep the
name semantics aligned with the existing RDMA rename path.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/device.c | 6 ++++++
drivers/infiniband/core/nldev.c | 27 ++++++++++++++++++---------
include/uapi/rdma/rdma_netlink.h | 5 ++++-
3 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 2391bc7c8d23..8705011fab66 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1901,6 +1901,9 @@ int ib_device_set_netns_put(struct sk_buff *skb,
if (ret == -EEXIST)
NL_SET_ERR_MSG(extack,
"Device name already exists in the target net namespace");
+ else if (ret == -EINVAL && name)
+ NL_SET_ERR_MSG(extack,
+ "Unable to use requested device name in the target net namespace");
goto ns_err;
}
@@ -1931,6 +1934,9 @@ int ib_device_set_netns_put(struct sk_buff *skb,
if (ret == -EEXIST)
NL_SET_ERR_MSG(extack,
"Device name already exists in the target net namespace");
+ else if (ret == -EINVAL && name)
+ NL_SET_ERR_MSG(extack,
+ "Unable to use requested device name in the target net namespace");
put_net(net);
return ret;
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index 5fd1ef2c5050..473bf9667f83 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -1177,6 +1177,24 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
if (!device)
return -EINVAL;
+ if (tb[RDMA_NLDEV_NET_NS_FD]) {
+ char name[IB_DEVICE_NAME_MAX] = {};
+ u32 ns_fd;
+
+ if (tb[RDMA_NLDEV_ATTR_DEV_NAME]) {
+ nla_strscpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
+ IB_DEVICE_NAME_MAX);
+ if (strlen(name) == 0) {
+ err = -EINVAL;
+ goto done;
+ }
+ }
+ ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
+ err = ib_device_set_netns_put(skb, device, ns_fd,
+ name[0] ? name : NULL, extack);
+ goto put_done;
+ }
+
if (tb[RDMA_NLDEV_ATTR_DEV_NAME]) {
char name[IB_DEVICE_NAME_MAX] = {};
@@ -1190,15 +1208,6 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
goto done;
}
- if (tb[RDMA_NLDEV_NET_NS_FD]) {
- u32 ns_fd;
-
- ns_fd = nla_get_u32(tb[RDMA_NLDEV_NET_NS_FD]);
- err = ib_device_set_netns_put(skb, device, ns_fd, NULL,
- extack);
- goto put_done;
- }
-
if (tb[RDMA_NLDEV_ATTR_DEV_DIM]) {
u8 use_dim;
diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h
index 3af946ecbac3..ee11c3bbbae2 100644
--- a/include/uapi/rdma/rdma_netlink.h
+++ b/include/uapi/rdma/rdma_netlink.h
@@ -516,7 +516,10 @@ enum rdma_nldev_attr {
RDMA_NLDEV_ATTR_DEV_PROTOCOL, /* string */
/*
- * File descriptor handle of the net namespace object
+ * File descriptor handle of the net namespace object. May be combined
+ * with RDMA_NLDEV_ATTR_DEV_NAME (a literal device name) to also rename
+ * the device in the destination namespace; the move fails with -EEXIST
+ * if that name is already taken there.
*/
RDMA_NLDEV_NET_NS_FD, /* u32 */
/*
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH rdma-next 06/13] net/smc: Look up the pnetid ib device within the net namespace
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (4 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 05/13] RDMA/nldev: Allow setting the device name while changing net namespace Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-10 9:56 ` sashiko-bot
2026-07-09 9:55 ` [PATCH rdma-next 07/13] RDMA/srp: Make the SRP sysfs class net namespace aware Jiri Pirko
` (6 subsequent siblings)
12 siblings, 1 reply; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Scope smc_pnet_find_ib() to the caller's net namespace so pnetid setup
cannot bind to a same-named RDMA device from another namespace once names
become per-netns.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
net/smc/smc_pnet.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
index 63e286e2dfaa..ff9c9c35cc2f 100644
--- a/net/smc/smc_pnet.c
+++ b/net/smc/smc_pnet.c
@@ -304,13 +304,18 @@ static bool smc_pnetid_valid(const char *pnet_name, char *pnetid)
return true;
}
-/* Find an infiniband device by a given name. The device might not exist. */
-static struct smc_ib_device *smc_pnet_find_ib(char *ib_name)
+/*
+ * Find an infiniband device by a given name, restricted to the devices
+ * accessible from @net. The device might not exist.
+ */
+static struct smc_ib_device *smc_pnet_find_ib(struct net *net, char *ib_name)
{
struct smc_ib_device *ibdev;
mutex_lock(&smc_ib_devices.mutex);
list_for_each_entry(ibdev, &smc_ib_devices.list, list) {
+ if (!rdma_dev_access_netns(ibdev->ibdev, net))
+ continue;
if (!strncmp(ibdev->ibdev->name, ib_name,
sizeof(ibdev->ibdev->name)) ||
(ibdev->ibdev->dev.parent &&
@@ -408,8 +413,8 @@ static int smc_pnet_add_eth(struct smc_pnettable *pnettable, struct net *net,
return rc;
}
-static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name,
- u8 ib_port, char *pnet_name)
+static int smc_pnet_add_ib(struct smc_pnettable *pnettable, struct net *net,
+ char *ib_name, u8 ib_port, char *pnet_name)
{
struct smc_pnetentry *tmp_pe, *new_pe;
struct smc_ib_device *ib_dev;
@@ -419,7 +424,7 @@ static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name,
bool new_ibdev;
/* try to apply the pnetid to active devices */
- ib_dev = smc_pnet_find_ib(ib_name);
+ ib_dev = smc_pnet_find_ib(net, ib_name);
if (ib_dev) {
ibdev_applied = smc_pnet_apply_ib(ib_dev, ib_port, pnet_name);
if (ibdev_applied)
@@ -518,7 +523,7 @@ static int smc_pnet_enter(struct net *net, struct nlattr *tb[])
if (ibport < 1 || ibport > SMC_MAX_PORTS)
goto error;
}
- rc = smc_pnet_add_ib(pnettable, string, ibport, pnet_name);
+ rc = smc_pnet_add_ib(pnettable, net, string, ibport, pnet_name);
if (!rc)
new_ibdev = true;
else if (rc != -EEXIST)
@@ -1170,6 +1175,9 @@ int smc_pnetid_by_table_ib(struct smc_ib_device *smcibdev, u8 ib_port)
struct smc_net *sn;
int rc = -ENOENT;
+ if (!rdma_dev_access_netns(smcibdev->ibdev, &init_net))
+ return -ENOENT;
+
/* get pnettable for init namespace */
sn = net_generic(&init_net, smc_net_id);
pnettable = &sn->pnettable;
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH rdma-next 06/13] net/smc: Look up the pnetid ib device within the net namespace
2026-07-09 9:55 ` [PATCH rdma-next 06/13] net/smc: Look up the pnetid ib device within the " Jiri Pirko
@ 2026-07-10 9:56 ` sashiko-bot
0 siblings, 0 replies; 23+ messages in thread
From: sashiko-bot @ 2026-07-10 9:56 UTC (permalink / raw)
To: Jiri Pirko
Cc: Alexander Gordeev, Heiko Carstens, tj, mkoutny, hannes,
linux-s390, Vasily Gorbik
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Pre-existing TOCTOU and Use-After-Free race where `smc_pnet_find_ib()` and `smc_pnet_find_smcd()` return un-refcounted device pointers.
- [High] Pre-existing Use-After-Free during SMC connection setup due to un-refcounted `ib_dev` pointer in `smc_init_info`.
--
--- Patch [6]: [PATCH rdma-next 06/13] net/smc: Look up the pnetid ib device within the net namespace ---
commit d209b8afd09f2213c9477f5a717fdf012a7c2077
Author: Jiri Pirko <jiri@resnulli.us>
net/smc: Look up the pnetid ib device within the net namespace
This commit scopes smc_pnet_find_ib() to the caller's net namespace. It
ensures that pnetid setup cannot bind to a same-named RDMA device from
another namespace.
> diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
> index 63e286e2dfaa8..ff9c9c35cc2f5 100644
> --- a/net/smc/smc_pnet.c
> +++ b/net/smc/smc_pnet.c
> @@ -304,13 +304,18 @@ static bool smc_pnetid_valid(const char *pnet_name, char *pnetid)
> return true;
> }
>
> -/* Find an infiniband device by a given name. The device might not exist. */
> -static struct smc_ib_device *smc_pnet_find_ib(char *ib_name)
> +/*
> + * Find an infiniband device by a given name, restricted to the devices
> + * accessible from @net. The device might not exist.
> + */
> +static struct smc_ib_device *smc_pnet_find_ib(struct net *net, char *ib_name)
> {
> struct smc_ib_device *ibdev;
>
> mutex_lock(&smc_ib_devices.mutex);
> list_for_each_entry(ibdev, &smc_ib_devices.list, list) {
> + if (!rdma_dev_access_netns(ibdev->ibdev, net))
> + continue;
[ ... ]
> @@ -419,7 +424,7 @@ static int smc_pnet_add_ib(struct smc_pnettable *pnettable, char *ib_name,
> bool new_ibdev;
>
> /* try to apply the pnetid to active devices */
> - ib_dev = smc_pnet_find_ib(ib_name);
> + ib_dev = smc_pnet_find_ib(net, ib_name);
> if (ib_dev) {
> ibdev_applied = smc_pnet_apply_ib(ib_dev, ib_port, pnet_name);
> if (ibdev_applied)
[Severity: High]
This isn't a bug introduced by this patch, but smc_pnet_find_ib() in
net/smc/smc_pnet.c appears to return an un-refcounted device pointer.
If a user configures a PNETID for an IB or SMCD device via netlink and calls
smc_pnet_add_ib(), it locates the device in the global list while holding
smc_ib_devices.mutex. However, smc_pnet_find_ib() returns the raw pointer
after dropping the mutex.
If the device is concurrently hot-unplugged, smc_ib_remove_dev() or
smcd_unregister_dev() will acquire the mutex, remove the device from the
list, and kfree() the device structure.
Could the original netlink thread then continue execution and dereference the
now-freed pointer inside smc_pnet_apply_ib() or when printing
ib_dev->ibdev->name?
[Severity: High]
This is another pre-existing issue in net/smc/smc_pnet.c related to
un-refcounted pointers, but it happens during connection setup.
When a user calls connect() on an AF_SMC socket,
_smc_pnet_find_roce_by_pnetid() locates an active IB device while holding
smc_ib_devices.mutex, and stores its pointer in the smc_init_info structure
(ini->ib_dev) before dropping the mutex.
Connection establishment then continues across multiple function calls:
smc_find_proposal_devices() -> smc_connect_rdma() -> smc_conn_create()
using this un-refcounted pointer.
If the IB device is concurrently hot-unplugged, smc_ib_remove_dev() will
kfree() the device. Might the connection setup path then dereference the
freed memory?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260709095532.855647-1-jiri@resnulli.us?part=6
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH rdma-next 07/13] RDMA/srp: Make the SRP sysfs class net namespace aware
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (5 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 06/13] net/smc: Look up the pnetid ib device within the " Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace Jiri Pirko
` (5 subsequent siblings)
12 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Tag srp_class by the RDMA device's net namespace so SRP hosts derived from
same-named RDMA devices can coexist across namespaces.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/ulp/srp/ib_srp.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index acbd787de265..a070fcf86e8a 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -3189,10 +3189,24 @@ static struct attribute *srp_class_attrs[];
ATTRIBUTE_GROUPS(srp_class);
+/*
+ * SRP hosts are named after their ib device, so tag the class by the ib
+ * device's net namespace.
+ */
+static const struct ns_common *srp_net_namespace(const struct device *dev)
+{
+ struct srp_host *host = container_of(dev, struct srp_host, dev);
+ struct net *net = rdma_dev_net(host->srp_dev->dev);
+
+ return net ? to_ns_common(net) : NULL;
+}
+
static struct class srp_class = {
.name = "infiniband_srp",
.dev_groups = srp_class_groups,
- .dev_release = srp_release_dev
+ .dev_release = srp_release_dev,
+ .ns_type = &net_ns_type_operations,
+ .namespace = srp_net_namespace,
};
/**
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (6 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 07/13] RDMA/srp: Make the SRP sysfs class net namespace aware Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 13:04 ` Michal Koutný
2026-07-10 9:56 ` sashiko-bot
2026-07-09 9:55 ` [PATCH rdma-next 09/13] RDMA/cma: Document that CM configfs cannot be net namespace scoped Jiri Pirko
` (4 subsequent siblings)
12 siblings, 2 replies; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Track each rdma cgroup device's net namespace and sharing mode, then filter
name lookups and cgroupfs enumeration to devices visible from the caller's
namespace. Keep the cached sharing mode synchronized across registration,
netns moves, and runtime mode changes.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
Documentation/admin-guide/cgroup-v2.rst | 7 +++++++
drivers/infiniband/core/cgroup.c | 12 ++++++++++++
drivers/infiniband/core/core_priv.h | 12 ++++++++++++
drivers/infiniband/core/device.c | 11 +++++++++++
include/linux/cgroup_rdma.h | 10 ++++++++++
kernel/cgroup/rdma.c | 20 +++++++++++++++++++-
6 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst
index 993446ab66d0..4523c1884d67 100644
--- a/Documentation/admin-guide/cgroup-v2.rst
+++ b/Documentation/admin-guide/cgroup-v2.rst
@@ -2752,6 +2752,13 @@ RDMA
The "rdma" controller regulates the distribution and accounting of
RDMA resources.
+When RDMA devices are isolated per network namespace (exclusive mode),
+device names are unique only within a network namespace. The device lines
+below are therefore scoped to the reading or writing process's network
+namespace: only devices accessible from that namespace are listed, and a
+limit is applied to the device of that name in that namespace. Configure
+limits from the same network namespace as the workloads.
+
RDMA Interface Files
~~~~~~~~~~~~~~~~~~~~
diff --git a/drivers/infiniband/core/cgroup.c b/drivers/infiniband/core/cgroup.c
index 1f037fe01450..7a216ed45199 100644
--- a/drivers/infiniband/core/cgroup.c
+++ b/drivers/infiniband/core/cgroup.c
@@ -17,6 +17,8 @@
void ib_device_register_rdmacg(struct ib_device *device)
{
device->cg_device.name = device->name;
+ device->cg_device.netns_shared = ib_devices_shared_netns;
+ write_pnet(&device->cg_device.net, rdma_dev_net(device));
rdmacg_register_device(&device->cg_device);
}
@@ -34,6 +36,16 @@ void ib_device_unregister_rdmacg(struct ib_device *device)
rdmacg_unregister_device(&device->cg_device);
}
+void ib_device_rdmacg_change_netns(struct ib_device *device, struct net *net)
+{
+ write_pnet(&device->cg_device.net, net);
+}
+
+void ib_device_rdmacg_set_netns_shared(struct ib_device *device, bool shared)
+{
+ WRITE_ONCE(device->cg_device.netns_shared, shared);
+}
+
int ib_rdmacg_try_charge(struct ib_rdmacg_object *cg_obj,
struct ib_device *device,
enum rdmacg_resource_type resource_index)
diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h
index aaf330b0d333..9cd671e2db20 100644
--- a/drivers/infiniband/core/core_priv.h
+++ b/drivers/infiniband/core/core_priv.h
@@ -156,6 +156,8 @@ void ib_dispatch_event_clients(struct ib_event *event);
#ifdef CONFIG_CGROUP_RDMA
void ib_device_register_rdmacg(struct ib_device *device);
void ib_device_unregister_rdmacg(struct ib_device *device);
+void ib_device_rdmacg_change_netns(struct ib_device *device, struct net *net);
+void ib_device_rdmacg_set_netns_shared(struct ib_device *device, bool shared);
int ib_rdmacg_try_charge(struct ib_rdmacg_object *cg_obj,
struct ib_device *device,
@@ -173,6 +175,16 @@ static inline void ib_device_unregister_rdmacg(struct ib_device *device)
{
}
+static inline void ib_device_rdmacg_change_netns(struct ib_device *device,
+ struct net *net)
+{
+}
+
+static inline void ib_device_rdmacg_set_netns_shared(struct ib_device *device,
+ bool shared)
+{
+}
+
static inline int ib_rdmacg_try_charge(struct ib_rdmacg_object *cg_obj,
struct ib_device *device,
enum rdmacg_resource_type resource_index)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 8705011fab66..3ccf4731154a 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -1112,6 +1112,7 @@ static int add_all_compat_devs(void)
int rdma_compatdev_set(u8 enable)
{
struct rdma_dev_net *rnet;
+ struct ib_device *dev;
unsigned long index;
int ret = 0;
@@ -1134,6 +1135,12 @@ int rdma_compatdev_set(u8 enable)
if (ret)
return -EBUSY;
+ /* Keep each registered device's rdma cgroup visibility in sync. */
+ down_read(&devices_rwsem);
+ xa_for_each_marked(&devices, index, dev, DEVICE_REGISTERED)
+ ib_device_rdmacg_set_netns_shared(dev, enable);
+ up_read(&devices_rwsem);
+
if (enable)
ret = add_all_compat_devs();
else
@@ -1350,6 +1357,7 @@ static int enable_device_and_get(struct ib_device *device)
*/
refcount_set(&device->refcount, 2);
down_write(&devices_rwsem);
+ ib_device_rdmacg_set_netns_shared(device, ib_devices_shared_netns);
xa_set_mark(&devices, device->index, DEVICE_REGISTERED);
/*
@@ -1823,12 +1831,14 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
"%s: failed to pick device name during namespace teardown: %d\n",
__func__, ret);
write_pnet(&device->coredev.rdma_net, net);
+ ib_device_rdmacg_change_netns(device, net);
ret = 0;
}
goto rename_done;
}
write_pnet(&device->coredev.rdma_net, net);
+ ib_device_rdmacg_change_netns(device, net);
ret = device_rename(&device->dev, new_name);
if (ret) {
if (fallback_pattern) {
@@ -1842,6 +1852,7 @@ static int rdma_dev_change_netns(struct ib_device *device, struct net *cur_net,
__func__);
/* Try and put things back and re-enable the device */
write_pnet(&device->coredev.rdma_net, cur_net);
+ ib_device_rdmacg_change_netns(device, cur_net);
}
} else {
strscpy(device->name, dev_name(&device->dev),
diff --git a/include/linux/cgroup_rdma.h b/include/linux/cgroup_rdma.h
index 404e746552ca..71170cb0e19e 100644
--- a/include/linux/cgroup_rdma.h
+++ b/include/linux/cgroup_rdma.h
@@ -7,6 +7,7 @@
#define _CGROUP_RDMA_H
#include <linux/cgroup.h>
+#include <net/net_namespace.h>
enum rdmacg_resource_type {
RDMACG_RESOURCE_HCA_HANDLE,
@@ -34,6 +35,15 @@ struct rdmacg_device {
struct list_head dev_node;
struct list_head rpools;
char *name;
+ /*
+ * Net namespace the device belongs to. @netns_shared mirrors
+ * ib_devices_shared_netns: when true the device is visible from every
+ * net namespace (shared mode); otherwise @net is the only namespace
+ * that may see and configure it. @netns_shared is updated when the
+ * sharing mode changes, so use {READ,WRITE}_ONCE() to access it.
+ */
+ possible_net_t net;
+ bool netns_shared;
};
/*
diff --git a/kernel/cgroup/rdma.c b/kernel/cgroup/rdma.c
index 5e82a03b3270..c8b4e3de7630 100644
--- a/kernel/cgroup/rdma.c
+++ b/kernel/cgroup/rdma.c
@@ -15,6 +15,7 @@
#include <linux/cgroup.h>
#include <linux/parser.h>
#include <linux/cgroup_rdma.h>
+#include <linux/nsproxy.h>
#define RDMACG_MAX_STR "max"
@@ -464,6 +465,13 @@ void rdmacg_unregister_device(struct rdmacg_device *device)
}
EXPORT_SYMBOL(rdmacg_unregister_device);
+/* netns_shared is toggled without rdmacg_mutex, hence READ_ONCE(). */
+static bool rdmacg_device_visible(const struct rdmacg_device *device)
+{
+ return READ_ONCE(device->netns_shared) ||
+ net_eq(read_pnet(&device->net), current->nsproxy->net_ns);
+}
+
static struct rdmacg_device *rdmacg_get_device_locked(const char *name)
{
struct rdmacg_device *device;
@@ -471,7 +479,8 @@ static struct rdmacg_device *rdmacg_get_device_locked(const char *name)
lockdep_assert_held(&rdmacg_mutex);
list_for_each_entry(device, &rdmacg_devices, dev_node)
- if (!strcmp(name, device->name))
+ if (rdmacg_device_visible(device) &&
+ !strcmp(name, device->name))
return device;
return NULL;
@@ -626,6 +635,9 @@ static int rdmacg_resource_read(struct seq_file *sf, void *v)
mutex_lock(&rdmacg_mutex);
list_for_each_entry(device, &rdmacg_devices, dev_node) {
+ if (!rdmacg_device_visible(device))
+ continue;
+
seq_printf(sf, "%s ", device->name);
rpool = find_cg_rpool_locked(cg, device);
@@ -648,6 +660,9 @@ static int rdmacg_events_show(struct seq_file *sf, void *v)
mutex_lock(&rdmacg_mutex);
list_for_each_entry(device, &rdmacg_devices, dev_node) {
+ if (!rdmacg_device_visible(device))
+ continue;
+
rpool = find_cg_rpool_locked(cg, device);
seq_printf(sf, "%s ", device->name);
@@ -677,6 +692,9 @@ static int rdmacg_events_local_show(struct seq_file *sf, void *v)
mutex_lock(&rdmacg_mutex);
list_for_each_entry(device, &rdmacg_devices, dev_node) {
+ if (!rdmacg_device_visible(device))
+ continue;
+
rpool = find_cg_rpool_locked(cg, device);
seq_printf(sf, "%s ", device->name);
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace
2026-07-09 9:55 ` [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace Jiri Pirko
@ 2026-07-09 13:04 ` Michal Koutný
2026-07-10 9:56 ` sashiko-bot
1 sibling, 0 replies; 23+ messages in thread
From: Michal Koutný @ 2026-07-09 13:04 UTC (permalink / raw)
To: Jiri Pirko
Cc: linux-rdma, cgroups, netdev, linux-s390, linux-kselftest, jgg,
leon, parav, mbloch, cmeiohas, roman.gushchin, bvanassche,
zyjzyj2000, shuah, tj, hannes, alibuda, dust.li, sidraya, wenjia
[-- Attachment #1: Type: text/plain, Size: 1734 bytes --]
Hi.
On Thu, Jul 09, 2026 at 11:55:27AM +0200, Jiri Pirko <jiri@resnulli.us> wrote:
> index 993446ab66d0..4523c1884d67 100644
> --- a/Documentation/admin-guide/cgroup-v2.rst
> +++ b/Documentation/admin-guide/cgroup-v2.rst
> @@ -2752,6 +2752,13 @@ RDMA
> The "rdma" controller regulates the distribution and accounting of
> RDMA resources.
>
> +When RDMA devices are isolated per network namespace (exclusive mode),
> +device names are unique only within a network namespace. The device lines
> +below are therefore scoped to the reading or writing process's network
> +namespace: only devices accessible from that namespace are listed, and a
> +limit is applied to the device of that name in that namespace. Configure
> +limits from the same network namespace as the workloads.
OK.
> --- a/include/linux/cgroup_rdma.h
> +++ b/include/linux/cgroup_rdma.h
> @@ -7,6 +7,7 @@
> #define _CGROUP_RDMA_H
>
> #include <linux/cgroup.h>
> +#include <net/net_namespace.h>
>
> enum rdmacg_resource_type {
> RDMACG_RESOURCE_HCA_HANDLE,
> @@ -34,6 +35,15 @@ struct rdmacg_device {
> struct list_head dev_node;
> struct list_head rpools;
> char *name;
> + /*
> + * Net namespace the device belongs to. @netns_shared mirrors
> + * ib_devices_shared_netns: when true the device is visible from every
> + * net namespace (shared mode); otherwise @net is the only namespace
> + * that may see and configure it. @netns_shared is updated when the
> + * sharing mode changes, so use {READ,WRITE}_ONCE() to access it.
> + */
> + possible_net_t net;
> + bool netns_shared;
Any reason to store the netns_shared split per device? (IIUC, it's a
global parameter.)
Thanks,
Michal
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 265 bytes --]
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace
2026-07-09 9:55 ` [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace Jiri Pirko
2026-07-09 13:04 ` Michal Koutný
@ 2026-07-10 9:56 ` sashiko-bot
1 sibling, 0 replies; 23+ messages in thread
From: sashiko-bot @ 2026-07-10 9:56 UTC (permalink / raw)
To: Jiri Pirko
Cc: tj, mkoutny, Heiko Carstens, hannes, linux-s390,
Alexander Gordeev, Vasily Gorbik
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Scoping RDMA cgroup device visibility to the reader's network namespace breaks host-level cgroup administration and monitoring.
- [Medium] Concurrent lockless read of `device->net` using `read_pnet()` without `READ_ONCE()` leads to a data race.
--
--- Patch [8]: [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace ---
commit 18e4bddcfb08bd42bef710d6d1b72824d15fa2c9
Author: Jiri Pirko <jiri@resnulli.us>
RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace
Track each rdma cgroup device's net namespace and sharing mode, then filter
name lookups and cgroupfs enumeration to devices visible from the caller's
namespace. Keep the cached sharing mode synchronized across registration,
netns moves, and runtime mode changes.
> diff --git a/kernel/cgroup/rdma.c b/kernel/cgroup/rdma.c
> index 5e82a03b3270a..c8b4e3de76305 100644
> --- a/kernel/cgroup/rdma.c
> +++ b/kernel/cgroup/rdma.c
[ ... ]
> @@ -464,6 +465,13 @@ void rdmacg_unregister_device(struct rdmacg_device *device)
> }
> EXPORT_SYMBOL(rdmacg_unregister_device);
>
> +/* netns_shared is toggled without rdmacg_mutex, hence READ_ONCE(). */
> +static bool rdmacg_device_visible(const struct rdmacg_device *device)
> +{
> + return READ_ONCE(device->netns_shared) ||
> + net_eq(read_pnet(&device->net), current->nsproxy->net_ns);
[Severity: Medium]
Does this lockless read of device->net using read_pnet() cause a data race?
When another thread concurrently moves the RDMA device to a new network
namespace, it updates device->net:
drivers/infiniband/core/cgroup.c:ib_device_rdmacg_change_netns() {
write_pnet(&device->cg_device.net, net);
}
While write_pnet() uses rcu_assign_pointer() to update the pointer concurrently,
read_pnet() here expands to a plain pointer access without READ_ONCE(). Since
rdmacg_mutex is not held during the write, could this plain read race with the
assignment and cause undefined behavior?
[Severity: High]
Does tying RDMA cgroup device visibility to the reader's network namespace
break host-level cgroup administration and monitoring?
If a device is moved to a non-init network namespace (exclusive mode), host
administrators and orchestration tools (like systemd or Kubernetes running in
init_net) will completely lose visibility and control over its RDMA cgroup
resources. Attempting to write to rdma.max will result in -ENODEV, and reading
rdma.current will show an empty list for these devices.
Since cgroup state must reflect the cgroup's configuration independent of the
reading process's network namespace, does tying the UAPI to
current->nsproxy->net_ns violate VFS semantics where an open file descriptor's
behavior would dynamically change depending on which process calls write()?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260709095532.855647-1-jiri@resnulli.us?part=8
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH rdma-next 09/13] RDMA/cma: Document that CM configfs cannot be net namespace scoped
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (7 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 08/13] RDMA/cgroup: Scope rdma cgroup device visibility to the net namespace Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 10/13] RDMA/core: Document the SELinux ibendport net namespace limitation Jiri Pirko
` (3 subsequent siblings)
12 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Document the rdma_cm configfs limitation: configfs is global, so same-named
RDMA devices in different net namespaces cannot both be represented there.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
Documentation/ABI/testing/configfs-rdma_cm | 4 ++++
drivers/infiniband/core/cma_configfs.c | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/Documentation/ABI/testing/configfs-rdma_cm b/Documentation/ABI/testing/configfs-rdma_cm
index 74f9506f42e7..739f7b6a1259 100644
--- a/Documentation/ABI/testing/configfs-rdma_cm
+++ b/Documentation/ABI/testing/configfs-rdma_cm
@@ -12,6 +12,10 @@ Description: Interface is used to configure RDMA-cable HCAs in respect to
for this HCA has to be created:
mkdir -p /config/rdma_cm/<hca>
+ Note: configfs has no network namespace support, so this
+ interface cannot represent two devices that share a name in
+ different network namespaces (possible in exclusive netns mode).
+
What: /config/rdma_cm/<hca>/ports/<port-num>/default_roce_mode
Date: November 29, 2015
diff --git a/drivers/infiniband/core/cma_configfs.c b/drivers/infiniband/core/cma_configfs.c
index 891e52afb8f4..c389d4e37b6b 100644
--- a/drivers/infiniband/core/cma_configfs.c
+++ b/drivers/infiniband/core/cma_configfs.c
@@ -65,6 +65,10 @@ static struct cma_dev_port_group *to_dev_port_group(struct config_item *item)
return container_of(group, struct cma_dev_port_group, group);
}
+/*
+ * configfs is not net namespace aware, so a name shared by devices in
+ * different namespaces resolves to the first match here.
+ */
static bool filter_by_name(struct ib_device *ib_dev, void *cookie)
{
return !strcmp(dev_name(&ib_dev->dev), cookie);
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH rdma-next 10/13] RDMA/core: Document the SELinux ibendport net namespace limitation
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (8 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 09/13] RDMA/cma: Document that CM configfs cannot be net namespace scoped Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 11/13] RDMA/core: Make device names unique per net namespace Jiri Pirko
` (2 subsequent siblings)
12 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Document that SELinux ibendport labels use a global (device name, port)
key, so same-named RDMA devices in different net namespaces share a label.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/security.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/infiniband/core/security.c b/drivers/infiniband/core/security.c
index 9af31d1d9d70..a82c46965416 100644
--- a/drivers/infiniband/core/security.c
+++ b/drivers/infiniband/core/security.c
@@ -700,6 +700,12 @@ int ib_mad_agent_security_setup(struct ib_mad_agent *agent,
if (qp_type != IB_QPT_SMI)
return 0;
+ /*
+ * SELinux labels an endport by (device name, port) from a global
+ * policy. If devices in different net namespaces share a name, they get
+ * the same label; distinguishing them would need net namespace support
+ * in the policy language and tooling.
+ */
spin_lock(&mad_agent_list_lock);
ret = security_ib_endport_manage_subnet(agent->security,
dev_name(&agent->device->dev),
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH rdma-next 11/13] RDMA/core: Make device names unique per net namespace
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (9 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 10/13] RDMA/core: Document the SELinux ibendport net namespace limitation Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback Jiri Pirko
2026-07-09 9:55 ` [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test Jiri Pirko
12 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Use rdma_dev_access_netns() to scope RDMA device name lookup and "%d" name
allocation to the relevant net namespace. Keep shared mode and
CONFIG_NET_NS=n behaviour system-wide.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/core/device.c | 22 +++++++++++++++-------
1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 3ccf4731154a..cffb0de1c001 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -129,7 +129,7 @@ static DECLARE_RWSEM(rdma_nets_rwsem);
bool ib_devices_shared_netns = true;
module_param_named(netns_mode, ib_devices_shared_netns, bool, 0444);
MODULE_PARM_DESC(netns_mode,
- "Share device among net namespaces; default=1 (shared)");
+ "Share device among net namespaces; default=1 (shared). In exclusive mode device names are unique per net namespace");
/**
* rdma_dev_access_netns() - Return whether an rdma device can be accessed
* from a specified net namespace or not.
@@ -359,7 +359,8 @@ static struct ib_device *__ib_device_get_by_name(const char *name,
unsigned long index;
xa_for_each (&devices, index, device)
- if (!strcmp(name, dev_name(&device->dev)))
+ if (rdma_dev_access_netns(device, net) &&
+ !strcmp(name, dev_name(&device->dev)))
return device;
return NULL;
@@ -437,7 +438,11 @@ int ib_device_set_dim(struct ib_device *ibdev, u8 use_dim)
return 0;
}
-/* Pick a free index for the '%d' style @name pattern. */
+/*
+ * Pick a free index for the '%d' style @name pattern within net namespace
+ * @net. Returns the index on success or a negative errno. The caller builds
+ * the final unique device name from the returned index.
+ */
static int __alloc_name_id(struct net *net, const char *name,
const struct ib_device *skip)
{
@@ -452,7 +457,7 @@ static int __alloc_name_id(struct net *net, const char *name,
xa_for_each (&devices, index, device) {
char buf[IB_DEVICE_NAME_MAX];
- if (device == skip)
+ if (device == skip || !rdma_dev_access_netns(device, net))
continue;
if (sscanf(dev_name(&device->dev), name, &i) != 1)
continue;
@@ -1240,7 +1245,8 @@ static __net_init int rdma_dev_init_net(struct net *net)
}
/*
- * Assign the unique string device name and the unique device index. This is
+ * Assign the unique string device name and the unique device index. The device
+ * name is unique within the net namespace the device is assigned to. This is
* undone by ib_dealloc_device.
*/
static int assign_name(struct ib_device *device, const char *name)
@@ -1424,8 +1430,9 @@ static void ib_device_notify_register(struct ib_device *device)
/**
* ib_register_device - Register an IB device with IB core
* @device: Device to register
- * @name: unique string device name. This may include a '%' which will
- * cause a unique index to be added to the passed device name.
+ * @name: device name, unique within the device's net namespace. This may
+ * include a '%' which will cause a unique index to be added to the
+ * passed device name.
* @dma_device: pointer to a DMA-capable device. If %NULL, then the IB
* device will be used. In this case the caller should fully
* setup the ibdev for DMA. This usually means using dma_virt_ops.
@@ -1716,6 +1723,7 @@ static bool rdma_dev_name_in_netns(struct ib_device *skip, struct net *net,
xa_for_each(&devices, index, device)
if (device != skip &&
+ rdma_dev_access_netns(device, net) &&
!strcmp(name, dev_name(&device->dev)))
return true;
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (10 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 11/13] RDMA/core: Make device names unique per net namespace Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-10 4:21 ` Zhu Yanjun
2026-07-10 9:56 ` sashiko-bot
2026-07-09 9:55 ` [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test Jiri Pirko
12 siblings, 2 replies; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Implement an empty disassociate_ucontext() callback so the RDMA core
can move rxe devices between net namespaces. The core requires this
callback to reset user contexts without waiting for userspace.
rxe needs no teardown here: its user-mapped queues live in
reference-counted vmalloc memory (see rxe_mmap.c) that stays valid
while userspace holds the mappings.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
drivers/infiniband/sw/rxe/rxe_verbs.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index 1ec130fee8ea..6eb10d2f0653 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -240,6 +240,10 @@ static void rxe_dealloc_ucontext(struct ib_ucontext *ibuc)
rxe_err_uc(uc, "cleanup failed, err = %d\n", err);
}
+static void rxe_disassociate_ucontext(struct ib_ucontext *ibuc)
+{
+}
+
/* pd */
static int rxe_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
{
@@ -1478,6 +1482,7 @@ static const struct ib_device_ops rxe_dev_ops = {
.destroy_srq = rxe_destroy_srq,
.detach_mcast = rxe_detach_mcast,
.device_group = &rxe_attr_group,
+ .disassociate_ucontext = rxe_disassociate_ucontext,
.enable_driver = rxe_enable_driver,
.get_dma_mr = rxe_get_dma_mr,
.get_hw_stats = rxe_ib_get_hw_stats,
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback
2026-07-09 9:55 ` [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback Jiri Pirko
@ 2026-07-10 4:21 ` Zhu Yanjun
2026-07-10 9:56 ` sashiko-bot
1 sibling, 0 replies; 23+ messages in thread
From: Zhu Yanjun @ 2026-07-10 4:21 UTC (permalink / raw)
To: Jiri Pirko, linux-rdma, yanjun.zhu@linux.dev
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
在 2026/7/9 2:55, Jiri Pirko 写道:
> From: Jiri Pirko <jiri@nvidia.com>
>
> Implement an empty disassociate_ucontext() callback so the RDMA core
> can move rxe devices between net namespaces. The core requires this
> callback to reset user contexts without waiting for userspace.
>
> rxe needs no teardown here: its user-mapped queues live in
> reference-counted vmalloc memory (see rxe_mmap.c) that stays valid
> while userspace holds the mappings.
The logic here is correct for enabling netns migration. Since RXE's
user-mapped
queues rely on reference-counted vmalloc memory, this empty stub is safe
enough
to prevent kernel panics or Use-After-Free (UAF) during device movement.
However, as a note for future improvement: keeping this callback
entirely empty
means userspace won't be immediately notified (via SIGBUS or page table
zapping)
when the underlying device is moved out of its netns. For now, this
serves well as
a functional enabler, but we might want to introduce proper PTE
tearing/zap_vma_ptes()
down the road if applications require strict, immediate disconnection
semantics.
Thanks Jiri.
Reviewed-by: Yanjun Zhu <yanjun.zhu@linux.dev>
Zhu Yanjun
> Signed-off-by: Jiri Pirko <jiri@nvidia.com>
> ---
> drivers/infiniband/sw/rxe/rxe_verbs.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
> index 1ec130fee8ea..6eb10d2f0653 100644
> --- a/drivers/infiniband/sw/rxe/rxe_verbs.c
> +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
> @@ -240,6 +240,10 @@ static void rxe_dealloc_ucontext(struct ib_ucontext *ibuc)
> rxe_err_uc(uc, "cleanup failed, err = %d\n", err);
> }
>
> +static void rxe_disassociate_ucontext(struct ib_ucontext *ibuc)
> +{
> +}
> +
> /* pd */
> static int rxe_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
> {
> @@ -1478,6 +1482,7 @@ static const struct ib_device_ops rxe_dev_ops = {
> .destroy_srq = rxe_destroy_srq,
> .detach_mcast = rxe_detach_mcast,
> .device_group = &rxe_attr_group,
> + .disassociate_ucontext = rxe_disassociate_ucontext,
> .enable_driver = rxe_enable_driver,
> .get_dma_mr = rxe_get_dma_mr,
> .get_hw_stats = rxe_ib_get_hw_stats,
--
Best Regards,
Yanjun.Zhu
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback
2026-07-09 9:55 ` [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback Jiri Pirko
2026-07-10 4:21 ` Zhu Yanjun
@ 2026-07-10 9:56 ` sashiko-bot
1 sibling, 0 replies; 23+ messages in thread
From: sashiko-bot @ 2026-07-10 9:56 UTC (permalink / raw)
To: Jiri Pirko
Cc: Heiko Carstens, Alexander Gordeev, Vasily Gorbik, tj, linux-s390,
hannes, mkoutny
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] Implementing an empty `disassociate_ucontext` callback bypasses the core's VMA zapping because RXE uses legacy, untracked VMAs. This leads to a Use-After-Free of `ib_ucontext` and `rxe_dev` when the VMA is eventually closed, and potential kernel panics upon module unload.
--
--- Patch [12]: [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback ---
commit 8946fc9f2a378bad6f910a408699c6a70e97a6f6
Author: Jiri Pirko <jiri@resnulli.us>
RDMA/rxe: Implement disassociate_ucontext callback
Implement an empty disassociate_ucontext() callback so the RDMA core
can move rxe devices between net namespaces. The core requires this
callback to reset user contexts without waiting for userspace.
> diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
> index 1ec130fee8ea7..6eb10d2f0653b 100644
> --- a/drivers/infiniband/sw/rxe/rxe_verbs.c
> +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
> @@ -240,6 +240,10 @@ static void rxe_dealloc_ucontext(struct ib_ucontext *ibuc)
> rxe_err_uc(uc, "cleanup failed, err = %d\n", err);
> }
>
> +static void rxe_disassociate_ucontext(struct ib_ucontext *ibuc)
> +{
> +}
> +
[Severity: Critical]
By adding this callback, does this opt the driver into asynchronous teardown
which can lead to a use-after-free and kernel panic?
Because RXE uses legacy, untracked VMAs (bypassing the core's
rdma_user_mmap_entry mechanism), these VMAs are invisible to the core and are
not zapped during teardown.
If a user process maps an RXE resource and the device is then removed or
migrated to another network namespace, the asynchronous teardown will free
the ib_ucontext and allow module unload while the process still holds the VMA.
When the process later unmaps the memory or exits, the untracked VMA's close
callback (rxe_vma_close) will trigger rxe_mmap_release(), accessing the
already-freed ib_ucontext and rxe_dev:
drivers/infiniband/sw/rxe/rxe_mmap.c:rxe_mmap_release() {
struct rxe_mmap_info *ip = container_of(ref,
struct rxe_mmap_info, ref);
struct rxe_dev *rxe = to_rdev(ip->context->device);
spin_lock_bh(&rxe->pending_lock);
...
}
If the module was unloaded in the interim, jumping to the VMA's close callback
could also trigger an immediate kernel panic.
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260709095532.855647-1-jiri@resnulli.us?part=12
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test
2026-07-09 9:55 [PATCH rdma-next 00/13] RDMA: Make device names unique per net namespace Jiri Pirko
` (11 preceding siblings ...)
2026-07-09 9:55 ` [PATCH rdma-next 12/13] RDMA/rxe: Implement disassociate_ucontext callback Jiri Pirko
@ 2026-07-09 9:55 ` Jiri Pirko
2026-07-10 4:24 ` Zhu Yanjun
2026-07-10 9:56 ` sashiko-bot
12 siblings, 2 replies; 23+ messages in thread
From: Jiri Pirko @ 2026-07-09 9:55 UTC (permalink / raw)
To: linux-rdma
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
From: Jiri Pirko <jiri@nvidia.com>
Add a kselftest script that exercises per-netns RDMA device naming
with RXE. Cover duplicate names across namespaces, move conflict
handling, move-with-rename, and same-namespace rename requests.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
tools/testing/selftests/rdma/Makefile | 3 +-
tools/testing/selftests/rdma/config | 2 +
.../testing/selftests/rdma/rxe_netns_names.sh | 282 ++++++++++++++++++
3 files changed, 286 insertions(+), 1 deletion(-)
create mode 100755 tools/testing/selftests/rdma/rxe_netns_names.sh
diff --git a/tools/testing/selftests/rdma/Makefile b/tools/testing/selftests/rdma/Makefile
index 07af7f15c1bf..a91c14c45006 100644
--- a/tools/testing/selftests/rdma/Makefile
+++ b/tools/testing/selftests/rdma/Makefile
@@ -3,6 +3,7 @@ TEST_PROGS := rxe_rping_between_netns.sh \
rxe_ipv6.sh \
rxe_socket_with_netns.sh \
rxe_test_NETDEV_UNREGISTER.sh \
- rxe_sent_rcvd_bytes.sh
+ rxe_sent_rcvd_bytes.sh \
+ rxe_netns_names.sh
include ../lib.mk
diff --git a/tools/testing/selftests/rdma/config b/tools/testing/selftests/rdma/config
index 4ffb814e253b..e1ff54ec0f57 100644
--- a/tools/testing/selftests/rdma/config
+++ b/tools/testing/selftests/rdma/config
@@ -1,3 +1,5 @@
CONFIG_TUN
CONFIG_VETH
+CONFIG_DUMMY
+CONFIG_NET_NS
CONFIG_RDMA_RXE
diff --git a/tools/testing/selftests/rdma/rxe_netns_names.sh b/tools/testing/selftests/rdma/rxe_netns_names.sh
new file mode 100755
index 000000000000..a7e57706fdff
--- /dev/null
+++ b/tools/testing/selftests/rdma/rxe_netns_names.sh
@@ -0,0 +1,282 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Exercise RDMA device name handling across network namespaces.
+
+source "$(dirname "$0")/../kselftest/ktap_helpers.sh"
+
+NAME_PREFIX="rxe_netns_names_$$"
+NETDEV_PREFIX="rxn$$"
+NS1="${NAME_PREFIX}ns1"
+NS2="${NAME_PREFIX}ns2"
+RXE_A="${NAME_PREFIX}rxe_a"
+RXE_B="${NAME_PREFIX}rxe_b"
+RXE_SAME="${NAME_PREFIX}rxe_same"
+RXE_NEW="${NAME_PREFIX}rxe_new"
+DUMMY_A="${NETDEV_PREFIX}a"
+DUMMY_B="${NETDEV_PREFIX}b"
+OLD_MODE=""
+MODE_CHANGED=0
+MODS=("dummy" "rdma_rxe")
+TEST_SAME_NAMES="same RDMA device name can exist in two net namespaces"
+TEST_MOVE_CONFLICT="move without rename fails on destination name conflict"
+TEST_MOVE_RENAME="move then rename succeeds"
+TEST_COMBINED_MOVE_RENAME="move with requested destination name succeeds"
+TEST_SAME_NETNS_DUP_RENAME="same-netns rename rejects duplicate name"
+TEST_TEARDOWN_RETURN="netns delete returns device to init_net and renames on conflict"
+
+ksft_skip()
+{
+ ktap_skip_all "$*"
+ exit "$KSFT_SKIP"
+}
+
+fail()
+{
+ ktap_exit_fail_msg "$*"
+}
+
+need_cmd()
+{
+ command -v "$1" >/dev/null 2>&1 || ksft_skip "missing command: $1"
+}
+
+rdma_ns()
+{
+ local ns=$1
+
+ shift
+ ip netns exec "$ns" rdma "$@"
+}
+
+rdma_dev_exists()
+{
+ local ns=$1
+ local dev=$2
+
+ if [ -n "$ns" ]; then
+ rdma_ns "$ns" dev show "$dev" >/dev/null 2>&1
+ else
+ rdma dev show "$dev" >/dev/null 2>&1
+ fi
+}
+
+add_dummy()
+{
+ local netdev=$1
+
+ ip link add "$netdev" type dummy || return 1
+ ip link set "$netdev" up || return 1
+}
+
+add_rxe()
+{
+ local dev=$1
+ local netdev=$2
+
+ rdma link add "$dev" type rxe netdev "$netdev"
+}
+
+rdma_dev_on_netdev()
+{
+ local netdev=$1
+
+ rdma link show 2>/dev/null | awk -v want="$netdev" '
+ {
+ for (i = 1; i < NF; i++)
+ if ($i == "netdev" && $(i + 1) == want) {
+ dev = $2
+ sub(/\/.*/, "", dev)
+ print dev
+ exit
+ }
+ }'
+}
+
+wait_rdma_dev_on_netdev()
+{
+ local netdev=$1
+ local dev
+ local i
+
+ for i in $(seq 1 50); do
+ dev=$(rdma_dev_on_netdev "$netdev")
+ if [ -n "$dev" ]; then
+ echo "$dev"
+ return 0
+ fi
+ sleep 0.1
+ done
+
+ return 1
+}
+
+setup_devs()
+{
+ cleanup_devs
+
+ add_dummy "$DUMMY_A" || return 1
+ add_dummy "$DUMMY_B" || return 1
+
+ add_rxe "$RXE_A" "$DUMMY_A" || return 1
+ add_rxe "$RXE_B" "$DUMMY_B" || return 1
+}
+
+cleanup_devs()
+{
+ ip link del "$DUMMY_A" 2>/dev/null
+ ip link del "$DUMMY_B" 2>/dev/null
+}
+
+setup()
+{
+ OLD_MODE=$(rdma system show 2>/dev/null |
+ sed -n 's/.*netns \([^ ]*\).*/\1/p')
+ [ -n "$OLD_MODE" ] || ksft_skip "failed to read RDMA netns mode"
+
+ rdma system set netns exclusive >/dev/null 2>&1 ||
+ ksft_skip "rdma netns exclusive mode is not supported"
+ MODE_CHANGED=1
+
+ ip netns add "$NS1" || return 1
+ ip netns add "$NS2" || return 1
+}
+
+cleanup()
+{
+ cleanup_devs
+
+ ip netns del "$NS1" 2>/dev/null
+ ip netns del "$NS2" 2>/dev/null
+
+ if [ "$MODE_CHANGED" -eq 1 ]; then
+ rdma system set netns "$OLD_MODE" 2>/dev/null
+ fi
+
+ for m in "${MODS[@]}"; do
+ modprobe -r "$m" 2>/dev/null
+ done
+}
+
+rdma_supports_combined_move_rename()
+{
+ rdma dev help 2>&1 | grep -Eq 'netns .*name|name .*netns'
+}
+
+[ "$(id -u)" -eq 0 ] || ksft_skip "must be run as root"
+need_cmd ip
+need_cmd rdma
+need_cmd modprobe
+
+trap cleanup EXIT
+
+for m in "${MODS[@]}"; do
+ modinfo "$m" >/dev/null 2>&1 || ksft_skip "module $m not found"
+ modprobe "$m" || fail "failed to load $m"
+done
+
+setup || fail "failed to create net namespaces"
+
+ktap_print_header
+ktap_set_plan 7
+
+if setup_devs &&
+ rdma dev set "$RXE_A" netns "$NS1" &&
+ rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" &&
+ rdma dev set "$RXE_B" netns "$NS2" &&
+ rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" &&
+ rdma_dev_exists "$NS1" "$RXE_SAME" &&
+ rdma_dev_exists "$NS2" "$RXE_SAME"; then
+ ktap_test_pass "$TEST_SAME_NAMES"
+else
+ ktap_test_fail "$TEST_SAME_NAMES"
+fi
+cleanup_devs
+
+if ! setup_devs ||
+ ! rdma dev set "$RXE_A" netns "$NS1" ||
+ ! rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" ||
+ ! rdma dev set "$RXE_B" netns "$NS2" ||
+ ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME"; then
+ ktap_test_fail "$TEST_MOVE_CONFLICT"
+elif rdma_ns "$NS1" dev set "$RXE_SAME" netns "$NS2" >/dev/null 2>&1; then
+ ktap_test_fail "$TEST_MOVE_CONFLICT"
+elif rdma_dev_exists "$NS1" "$RXE_SAME" &&
+ rdma_dev_exists "$NS2" "$RXE_SAME"; then
+ ktap_test_pass "$TEST_MOVE_CONFLICT"
+else
+ ktap_test_fail "$TEST_MOVE_CONFLICT"
+fi
+cleanup_devs
+
+if ! setup_devs; then
+ ktap_test_fail "$TEST_MOVE_RENAME"
+elif rdma dev set "$RXE_A" netns "$NS2" &&
+ rdma_ns "$NS2" dev set "$RXE_A" name "$RXE_NEW"; then
+ if rdma_dev_exists "$NS2" "$RXE_NEW" &&
+ ! rdma_dev_exists "" "$RXE_A"; then
+ ktap_test_pass "$TEST_MOVE_RENAME"
+ else
+ ktap_test_fail "$TEST_MOVE_RENAME"
+ fi
+else
+ ktap_test_fail "$TEST_MOVE_RENAME"
+fi
+cleanup_devs
+
+if ! rdma_supports_combined_move_rename; then
+ ktap_test_skip "$TEST_COMBINED_MOVE_RENAME"
+elif ! setup_devs; then
+ ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
+elif rdma dev set "$RXE_A" netns "$NS2" name "$RXE_NEW"; then
+ if rdma_dev_exists "$NS2" "$RXE_NEW" &&
+ ! rdma_dev_exists "" "$RXE_A"; then
+ ktap_test_pass "$TEST_COMBINED_MOVE_RENAME"
+ else
+ ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
+ fi
+else
+ ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
+fi
+cleanup_devs
+
+if ! setup_devs; then
+ ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
+elif rdma dev set "$RXE_A" name "$RXE_SAME" &&
+ rdma dev set "$RXE_B" name "$RXE_NEW"; then
+ if rdma dev set "$RXE_A" name "$RXE_NEW" >/dev/null 2>&1; then
+ ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
+ elif rdma_dev_exists "" "$RXE_SAME" &&
+ rdma_dev_exists "" "$RXE_NEW"; then
+ ktap_test_pass "$TEST_SAME_NETNS_DUP_RENAME"
+ else
+ ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
+ fi
+else
+ ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
+fi
+cleanup_devs
+
+if ! setup_devs; then
+ ktap_test_fail "$TEST_TEARDOWN_RETURN"
+elif ! rdma dev set "$RXE_A" name "$RXE_SAME" ||
+ ! rdma dev set "$RXE_B" netns "$NS2" ||
+ ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" ||
+ ! rdma_dev_exists "$NS2" "$RXE_SAME"; then
+ ktap_test_fail "$TEST_TEARDOWN_RETURN"
+else
+ ip netns del "$NS2"
+ returned=$(wait_rdma_dev_on_netdev "$DUMMY_B")
+ ktap_print_msg "device returned to init_net as '${returned:-<missing>}'"
+ if rdma_dev_exists "" "$RXE_SAME" &&
+ [ -n "$returned" ] &&
+ [ "$returned" != "$RXE_SAME" ] &&
+ [ "${returned#ibdev}" != "$returned" ]; then
+ ktap_test_pass "$TEST_TEARDOWN_RETURN"
+ else
+ ktap_test_fail "$TEST_TEARDOWN_RETURN"
+ fi
+fi
+cleanup_devs
+
+ktap_finished
--
2.54.0
^ permalink raw reply related [flat|nested] 23+ messages in thread* Re: [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test
2026-07-09 9:55 ` [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test Jiri Pirko
@ 2026-07-10 4:24 ` Zhu Yanjun
2026-07-10 9:56 ` sashiko-bot
1 sibling, 0 replies; 23+ messages in thread
From: Zhu Yanjun @ 2026-07-10 4:24 UTC (permalink / raw)
To: Jiri Pirko, linux-rdma, yanjun.zhu@linux.dev
Cc: cgroups, netdev, linux-s390, linux-kselftest, jgg, leon, parav,
mbloch, cmeiohas, roman.gushchin, bvanassche, zyjzyj2000, shuah,
tj, mkoutny, hannes, alibuda, dust.li, sidraya, wenjia
在 2026/7/9 2:55, Jiri Pirko 写道:
> From: Jiri Pirko <jiri@nvidia.com>
>
> Add a kselftest script that exercises per-netns RDMA device naming
> with RXE. Cover duplicate names across namespaces, move conflict
> handling, move-with-rename, and same-namespace rename requests.
This is a very comprehensive test suite for the per-netns RDMA device
naming infra.
I especially appreciate the inclusion of the 'TEST_TEARDOWN_RETURN'
case—ensuring
that the kernel's automatic renaming and fallback mechanics work
seamlessly during
netns deletion is crucial for long-term stability.
One minor thing to clean up before pushing to the tree: the script
declares 'ktap_set_plan 7'
but actually defines 6 distinct test cases in the execution block. I
will fix this plan count to 6
to avoid any "bad plan" warnings in automated CI frameworks (like KernelCI).
Aside from that, the cleanup paths and setup tracking are solid.
Thanks for adding this.
Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev>
Zhu Yanjun
>
> Signed-off-by: Jiri Pirko <jiri@nvidia.com>
> ---
> tools/testing/selftests/rdma/Makefile | 3 +-
> tools/testing/selftests/rdma/config | 2 +
> .../testing/selftests/rdma/rxe_netns_names.sh | 282 ++++++++++++++++++
> 3 files changed, 286 insertions(+), 1 deletion(-)
> create mode 100755 tools/testing/selftests/rdma/rxe_netns_names.sh
>
> diff --git a/tools/testing/selftests/rdma/Makefile b/tools/testing/selftests/rdma/Makefile
> index 07af7f15c1bf..a91c14c45006 100644
> --- a/tools/testing/selftests/rdma/Makefile
> +++ b/tools/testing/selftests/rdma/Makefile
> @@ -3,6 +3,7 @@ TEST_PROGS := rxe_rping_between_netns.sh \
> rxe_ipv6.sh \
> rxe_socket_with_netns.sh \
> rxe_test_NETDEV_UNREGISTER.sh \
> - rxe_sent_rcvd_bytes.sh
> + rxe_sent_rcvd_bytes.sh \
> + rxe_netns_names.sh
>
> include ../lib.mk
> diff --git a/tools/testing/selftests/rdma/config b/tools/testing/selftests/rdma/config
> index 4ffb814e253b..e1ff54ec0f57 100644
> --- a/tools/testing/selftests/rdma/config
> +++ b/tools/testing/selftests/rdma/config
> @@ -1,3 +1,5 @@
> CONFIG_TUN
> CONFIG_VETH
> +CONFIG_DUMMY
> +CONFIG_NET_NS
> CONFIG_RDMA_RXE
> diff --git a/tools/testing/selftests/rdma/rxe_netns_names.sh b/tools/testing/selftests/rdma/rxe_netns_names.sh
> new file mode 100755
> index 000000000000..a7e57706fdff
> --- /dev/null
> +++ b/tools/testing/selftests/rdma/rxe_netns_names.sh
> @@ -0,0 +1,282 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Exercise RDMA device name handling across network namespaces.
> +
> +source "$(dirname "$0")/../kselftest/ktap_helpers.sh"
> +
> +NAME_PREFIX="rxe_netns_names_$$"
> +NETDEV_PREFIX="rxn$$"
> +NS1="${NAME_PREFIX}ns1"
> +NS2="${NAME_PREFIX}ns2"
> +RXE_A="${NAME_PREFIX}rxe_a"
> +RXE_B="${NAME_PREFIX}rxe_b"
> +RXE_SAME="${NAME_PREFIX}rxe_same"
> +RXE_NEW="${NAME_PREFIX}rxe_new"
> +DUMMY_A="${NETDEV_PREFIX}a"
> +DUMMY_B="${NETDEV_PREFIX}b"
> +OLD_MODE=""
> +MODE_CHANGED=0
> +MODS=("dummy" "rdma_rxe")
> +TEST_SAME_NAMES="same RDMA device name can exist in two net namespaces"
> +TEST_MOVE_CONFLICT="move without rename fails on destination name conflict"
> +TEST_MOVE_RENAME="move then rename succeeds"
> +TEST_COMBINED_MOVE_RENAME="move with requested destination name succeeds"
> +TEST_SAME_NETNS_DUP_RENAME="same-netns rename rejects duplicate name"
> +TEST_TEARDOWN_RETURN="netns delete returns device to init_net and renames on conflict"
> +
> +ksft_skip()
> +{
> + ktap_skip_all "$*"
> + exit "$KSFT_SKIP"
> +}
> +
> +fail()
> +{
> + ktap_exit_fail_msg "$*"
> +}
> +
> +need_cmd()
> +{
> + command -v "$1" >/dev/null 2>&1 || ksft_skip "missing command: $1"
> +}
> +
> +rdma_ns()
> +{
> + local ns=$1
> +
> + shift
> + ip netns exec "$ns" rdma "$@"
> +}
> +
> +rdma_dev_exists()
> +{
> + local ns=$1
> + local dev=$2
> +
> + if [ -n "$ns" ]; then
> + rdma_ns "$ns" dev show "$dev" >/dev/null 2>&1
> + else
> + rdma dev show "$dev" >/dev/null 2>&1
> + fi
> +}
> +
> +add_dummy()
> +{
> + local netdev=$1
> +
> + ip link add "$netdev" type dummy || return 1
> + ip link set "$netdev" up || return 1
> +}
> +
> +add_rxe()
> +{
> + local dev=$1
> + local netdev=$2
> +
> + rdma link add "$dev" type rxe netdev "$netdev"
> +}
> +
> +rdma_dev_on_netdev()
> +{
> + local netdev=$1
> +
> + rdma link show 2>/dev/null | awk -v want="$netdev" '
> + {
> + for (i = 1; i < NF; i++)
> + if ($i == "netdev" && $(i + 1) == want) {
> + dev = $2
> + sub(/\/.*/, "", dev)
> + print dev
> + exit
> + }
> + }'
> +}
> +
> +wait_rdma_dev_on_netdev()
> +{
> + local netdev=$1
> + local dev
> + local i
> +
> + for i in $(seq 1 50); do
> + dev=$(rdma_dev_on_netdev "$netdev")
> + if [ -n "$dev" ]; then
> + echo "$dev"
> + return 0
> + fi
> + sleep 0.1
> + done
> +
> + return 1
> +}
> +
> +setup_devs()
> +{
> + cleanup_devs
> +
> + add_dummy "$DUMMY_A" || return 1
> + add_dummy "$DUMMY_B" || return 1
> +
> + add_rxe "$RXE_A" "$DUMMY_A" || return 1
> + add_rxe "$RXE_B" "$DUMMY_B" || return 1
> +}
> +
> +cleanup_devs()
> +{
> + ip link del "$DUMMY_A" 2>/dev/null
> + ip link del "$DUMMY_B" 2>/dev/null
> +}
> +
> +setup()
> +{
> + OLD_MODE=$(rdma system show 2>/dev/null |
> + sed -n 's/.*netns \([^ ]*\).*/\1/p')
> + [ -n "$OLD_MODE" ] || ksft_skip "failed to read RDMA netns mode"
> +
> + rdma system set netns exclusive >/dev/null 2>&1 ||
> + ksft_skip "rdma netns exclusive mode is not supported"
> + MODE_CHANGED=1
> +
> + ip netns add "$NS1" || return 1
> + ip netns add "$NS2" || return 1
> +}
> +
> +cleanup()
> +{
> + cleanup_devs
> +
> + ip netns del "$NS1" 2>/dev/null
> + ip netns del "$NS2" 2>/dev/null
> +
> + if [ "$MODE_CHANGED" -eq 1 ]; then
> + rdma system set netns "$OLD_MODE" 2>/dev/null
> + fi
> +
> + for m in "${MODS[@]}"; do
> + modprobe -r "$m" 2>/dev/null
> + done
> +}
> +
> +rdma_supports_combined_move_rename()
> +{
> + rdma dev help 2>&1 | grep -Eq 'netns .*name|name .*netns'
> +}
> +
> +[ "$(id -u)" -eq 0 ] || ksft_skip "must be run as root"
> +need_cmd ip
> +need_cmd rdma
> +need_cmd modprobe
> +
> +trap cleanup EXIT
> +
> +for m in "${MODS[@]}"; do
> + modinfo "$m" >/dev/null 2>&1 || ksft_skip "module $m not found"
> + modprobe "$m" || fail "failed to load $m"
> +done
> +
> +setup || fail "failed to create net namespaces"
> +
> +ktap_print_header
> +ktap_set_plan 7
> +
> +if setup_devs &&
> + rdma dev set "$RXE_A" netns "$NS1" &&
> + rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" &&
> + rdma dev set "$RXE_B" netns "$NS2" &&
> + rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" &&
> + rdma_dev_exists "$NS1" "$RXE_SAME" &&
> + rdma_dev_exists "$NS2" "$RXE_SAME"; then
> + ktap_test_pass "$TEST_SAME_NAMES"
> +else
> + ktap_test_fail "$TEST_SAME_NAMES"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs ||
> + ! rdma dev set "$RXE_A" netns "$NS1" ||
> + ! rdma_ns "$NS1" dev set "$RXE_A" name "$RXE_SAME" ||
> + ! rdma dev set "$RXE_B" netns "$NS2" ||
> + ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME"; then
> + ktap_test_fail "$TEST_MOVE_CONFLICT"
> +elif rdma_ns "$NS1" dev set "$RXE_SAME" netns "$NS2" >/dev/null 2>&1; then
> + ktap_test_fail "$TEST_MOVE_CONFLICT"
> +elif rdma_dev_exists "$NS1" "$RXE_SAME" &&
> + rdma_dev_exists "$NS2" "$RXE_SAME"; then
> + ktap_test_pass "$TEST_MOVE_CONFLICT"
> +else
> + ktap_test_fail "$TEST_MOVE_CONFLICT"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs; then
> + ktap_test_fail "$TEST_MOVE_RENAME"
> +elif rdma dev set "$RXE_A" netns "$NS2" &&
> + rdma_ns "$NS2" dev set "$RXE_A" name "$RXE_NEW"; then
> + if rdma_dev_exists "$NS2" "$RXE_NEW" &&
> + ! rdma_dev_exists "" "$RXE_A"; then
> + ktap_test_pass "$TEST_MOVE_RENAME"
> + else
> + ktap_test_fail "$TEST_MOVE_RENAME"
> + fi
> +else
> + ktap_test_fail "$TEST_MOVE_RENAME"
> +fi
> +cleanup_devs
> +
> +if ! rdma_supports_combined_move_rename; then
> + ktap_test_skip "$TEST_COMBINED_MOVE_RENAME"
> +elif ! setup_devs; then
> + ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
> +elif rdma dev set "$RXE_A" netns "$NS2" name "$RXE_NEW"; then
> + if rdma_dev_exists "$NS2" "$RXE_NEW" &&
> + ! rdma_dev_exists "" "$RXE_A"; then
> + ktap_test_pass "$TEST_COMBINED_MOVE_RENAME"
> + else
> + ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
> + fi
> +else
> + ktap_test_fail "$TEST_COMBINED_MOVE_RENAME"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs; then
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> +elif rdma dev set "$RXE_A" name "$RXE_SAME" &&
> + rdma dev set "$RXE_B" name "$RXE_NEW"; then
> + if rdma dev set "$RXE_A" name "$RXE_NEW" >/dev/null 2>&1; then
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> + elif rdma_dev_exists "" "$RXE_SAME" &&
> + rdma_dev_exists "" "$RXE_NEW"; then
> + ktap_test_pass "$TEST_SAME_NETNS_DUP_RENAME"
> + else
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> + fi
> +else
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> +fi
> +cleanup_devs
> +
> +if ! setup_devs; then
> + ktap_test_fail "$TEST_TEARDOWN_RETURN"
> +elif ! rdma dev set "$RXE_A" name "$RXE_SAME" ||
> + ! rdma dev set "$RXE_B" netns "$NS2" ||
> + ! rdma_ns "$NS2" dev set "$RXE_B" name "$RXE_SAME" ||
> + ! rdma_dev_exists "$NS2" "$RXE_SAME"; then
> + ktap_test_fail "$TEST_TEARDOWN_RETURN"
> +else
> + ip netns del "$NS2"
> + returned=$(wait_rdma_dev_on_netdev "$DUMMY_B")
> + ktap_print_msg "device returned to init_net as '${returned:-<missing>}'"
> + if rdma_dev_exists "" "$RXE_SAME" &&
> + [ -n "$returned" ] &&
> + [ "$returned" != "$RXE_SAME" ] &&
> + [ "${returned#ibdev}" != "$returned" ]; then
> + ktap_test_pass "$TEST_TEARDOWN_RETURN"
> + else
> + ktap_test_fail "$TEST_TEARDOWN_RETURN"
> + fi
> +fi
> +cleanup_devs
> +
> +ktap_finished
--
Best Regards,
Yanjun.Zhu
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test
2026-07-09 9:55 ` [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test Jiri Pirko
2026-07-10 4:24 ` Zhu Yanjun
@ 2026-07-10 9:56 ` sashiko-bot
1 sibling, 0 replies; 23+ messages in thread
From: sashiko-bot @ 2026-07-10 9:56 UTC (permalink / raw)
To: Jiri Pirko
Cc: Vasily Gorbik, tj, mkoutny, linux-s390, Heiko Carstens,
Alexander Gordeev, hannes
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] The test script declares a test plan of 7 tests, but only contains logic to execute 6 tests, causing the script to unconditionally fail.
- [Medium] The test `TEST_SAME_NETNS_DUP_RENAME` attempts to rename a non-existent device, causing the test to pass for the wrong reason and failing to verify duplicate name rejection.
--
--- Patch [13]: [PATCH rdma-next 13/13] RDMA/selftests: Add rxe_netns_names test ---
commit abd8a5c3d2f106017be1f5b869afa69da9c27f3a
Author: Jiri Pirko <jiri@resnulli.us>
RDMA/selftests: Add rxe_netns_names test
This commit adds a kselftest script that exercises per-netns RDMA device
naming with RXE. It covers duplicate names across namespaces, move conflict
handling, move-with-rename, and same-namespace rename requests.
> diff --git a/tools/testing/selftests/rdma/rxe_netns_names.sh b/tools/testing/selftests/rdma/rxe_netns_names.sh
> new file mode 100755
> index 0000000000000..a7e57706fdff7
> --- /dev/null
> +++ b/tools/testing/selftests/rdma/rxe_netns_names.sh
[ ... ]
> +setup || fail "failed to create net namespaces"
> +
> +ktap_print_header
> +ktap_set_plan 7
[Severity: Medium]
Does this plan count match the number of tests executed? It looks like the
script only runs 6 tests, which would cause the test suite to unconditionally
fail during ktap_finished due to a missing test.
> +
> +if setup_devs &&
[ ... ]
> +if ! setup_devs; then
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> +elif rdma dev set "$RXE_A" name "$RXE_SAME" &&
> + rdma dev set "$RXE_B" name "$RXE_NEW"; then
> + if rdma dev set "$RXE_A" name "$RXE_NEW" >/dev/null 2>&1; then
[Severity: Medium]
Will this command fail because of a duplicate name, or because the device
is missing?
The device originally named RXE_A was just renamed to RXE_SAME in the previous
condition. If we attempt to rename RXE_A again here, the command fails due to
the device not being found, which seems to cause the test to pass for the
wrong reason instead of properly verifying duplicate name rejection.
> + ktap_test_fail "$TEST_SAME_NETNS_DUP_RENAME"
> + elif rdma_dev_exists "" "$RXE_SAME" &&
> + rdma_dev_exists "" "$RXE_NEW"; then
> + ktap_test_pass "$TEST_SAME_NETNS_DUP_RENAME"
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260709095532.855647-1-jiri@resnulli.us?part=13
^ permalink raw reply [flat|nested] 23+ messages in thread