* [PATCH net v2] net: qualcomm: rmnet: require real-netns admin for bridging
@ 2026-10-04 20:31 Jérémy Jean
2026-10-04 20:33 ` netdev-bot+sinfo
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Jérémy Jean @ 2026-10-04 20:31 UTC (permalink / raw)
To: Subash Abhinov Kasiviswanathan, Sean Tranchetti
Cc: netdev, linux-kernel, Jérémy Jean, stable
An rmnet device keeps its link to the real device when moved to another
network namespace. The bridge callbacks change the real port, but rtnetlink
only checks CAP_NET_ADMIN in the slave device's namespace.
Require CAP_NET_ADMIN in the real device's namespace before adding or
removing a bridge. Use the slave device's namespace for the comparison,
since that is the namespace rtnetlink authorized.
Fixes: 60d58f971c10 ("net: qualcomm: rmnet: Implement bridge mode")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
---
Changes in v2, after Subash Abhinov's review:
- Add the teardown check and use slave_dev for both capability checks.
v1: https://lore.kernel.org/all/20260821202845.4053530-2-Jeremy.Jean@oss.cyber.gouv.fr/
.../ethernet/qualcomm/rmnet/rmnet_config.c | 20 ++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
index bed6f63facf2..62d7acb13e0c 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
@@ -441,6 +441,13 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
struct rmnet_port *port, *slave_port;
int err;
+ /* The rtnl path only checks CAP_NET_ADMIN against dev_net(slave_dev),
+ * but bridge mode below controls real_dev, which may live in another
+ * netns.
+ */
+ if (!rtnl_dev_link_net_capable(slave_dev, dev_net(real_dev)))
+ return -EPERM;
+
port = rmnet_get_port_rtnl(real_dev);
/* If there is more than one rmnet dev attached, its probably being
@@ -489,7 +496,18 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
int rmnet_del_bridge(struct net_device *rmnet_dev,
struct net_device *slave_dev)
{
- struct rmnet_port *port = rmnet_get_port_rtnl(slave_dev);
+ struct rmnet_priv *priv = netdev_priv(rmnet_dev);
+ struct net_device *real_dev = priv->real_dev;
+ struct rmnet_port *port;
+
+ /* The rtnl path only checks CAP_NET_ADMIN against dev_net(slave_dev),
+ * but bridge teardown also updates real_dev, which may live in another
+ * netns.
+ */
+ if (!rtnl_dev_link_net_capable(slave_dev, dev_net(real_dev)))
+ return -EPERM;
+
+ port = rmnet_get_port_rtnl(slave_dev);
rmnet_unregister_bridge(port);
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net v2] net: qualcomm: rmnet: require real-netns admin for bridging
2026-10-04 20:31 [PATCH net v2] net: qualcomm: rmnet: require real-netns admin for bridging Jérémy Jean
@ 2026-10-04 20:33 ` netdev-bot+sinfo
2026-10-05 5:46 ` subash.a.kasiviswanathan
2026-10-05 21:06 ` netdev-bot+sashiko
2 siblings, 0 replies; 5+ messages in thread
From: netdev-bot+sinfo @ 2026-10-04 20:33 UTC (permalink / raw)
To: Jérémy Jean
Cc: Subash Abhinov Kasiviswanathan, Sean Tranchetti, netdev,
linux-kernel, stable
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- How the issue was discovered, e.g. hit in production, hit during
development, syzbot report, manual code inspection, LLM or static
analysis tool scan.
- Whether the issue was actually triggered, or is only theoretical
(e.g. found by code inspection). If it was triggered please include
the symptoms, like the stack trace or error messages.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 5+ messages in thread
* RE: [PATCH net v2] net: qualcomm: rmnet: require real-netns admin for bridging
2026-10-04 20:31 [PATCH net v2] net: qualcomm: rmnet: require real-netns admin for bridging Jérémy Jean
2026-10-04 20:33 ` netdev-bot+sinfo
@ 2026-10-05 5:46 ` subash.a.kasiviswanathan
2026-10-05 8:16 ` Jérémy Jean
2026-10-05 21:06 ` netdev-bot+sashiko
2 siblings, 1 reply; 5+ messages in thread
From: subash.a.kasiviswanathan @ 2026-10-05 5:46 UTC (permalink / raw)
To: 'Jérémy Jean', 'Sean Tranchetti'
Cc: netdev, linux-kernel, stable
> -----Original Message-----
> From: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
> Sent: Sunday, October 4, 2026 2:32 PM
> To: Subash Abhinov Kasiviswanathan
> <subash.a.kasiviswanathan@oss.qualcomm.com>; Sean Tranchetti
> <sean.tranchetti@oss.qualcomm.com>
> Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Jérémy Jean
> <Jeremy.Jean@oss.cyber.gouv.fr>; stable@vger.kernel.org
> Subject: [PATCH net v2] net: qualcomm: rmnet: require real-netns admin for
> bridging
>
> An rmnet device keeps its link to the real device when moved to another
> network namespace. The bridge callbacks change the real port, but rtnetlink
> only checks CAP_NET_ADMIN in the slave device's namespace.
>
> Require CAP_NET_ADMIN in the real device's namespace before adding or
> removing a bridge. Use the slave device's namespace for the comparison, since
> that is the namespace rtnetlink authorized.
>
> Fixes: 60d58f971c10 ("net: qualcomm: rmnet: Implement bridge mode")
> Cc: stable@vger.kernel.org
> Assisted-by: LLM
> Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
> ---
>
> Changes in v2, after Subash Abhinov's review:
> - Add the teardown check and use slave_dev for both capability checks.
>
> v1: https://lore.kernel.org/all/20260821202845.4053530-2-
> Jeremy.Jean@oss.cyber.gouv.fr/
>
> .../ethernet/qualcomm/rmnet/rmnet_config.c | 20
> ++++++++++++++++++-
> 1 file changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
> b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
> index bed6f63facf2..62d7acb13e0c 100644
> --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
> +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
> @@ -441,6 +441,13 @@ int rmnet_add_bridge(struct net_device
> *rmnet_dev,
> struct rmnet_port *port, *slave_port;
> int err;
>
> + /* The rtnl path only checks CAP_NET_ADMIN against
> dev_net(slave_dev),
> + * but bridge mode below controls real_dev, which may live in another
> + * netns.
> + */
> + if (!rtnl_dev_link_net_capable(slave_dev, dev_net(real_dev)))
> + return -EPERM;
> +
> port = rmnet_get_port_rtnl(real_dev);
>
> /* If there is more than one rmnet dev attached, its probably being
> @@ -489,7 +496,18 @@ int rmnet_add_bridge(struct net_device
> *rmnet_dev, int rmnet_del_bridge(struct net_device *rmnet_dev,
> struct net_device *slave_dev)
> {
> - struct rmnet_port *port = rmnet_get_port_rtnl(slave_dev);
> + struct rmnet_priv *priv = netdev_priv(rmnet_dev);
> + struct net_device *real_dev = priv->real_dev;
> + struct rmnet_port *port;
> +
> + /* The rtnl path only checks CAP_NET_ADMIN against
> dev_net(slave_dev),
> + * but bridge teardown also updates real_dev, which may live in
> another
> + * netns.
> + */
> + if (!rtnl_dev_link_net_capable(slave_dev, dev_net(real_dev)))
> + return -EPERM;
> +
> + port = rmnet_get_port_rtnl(slave_dev);
>
> rmnet_unregister_bridge(port);
>
A similar patch was committed recently in net-next. Please refer to https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=26ee8cd69d46a14b37ba5e512084fe80d730127a
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net v2] net: qualcomm: rmnet: require real-netns admin for bridging
2026-10-05 5:46 ` subash.a.kasiviswanathan
@ 2026-10-05 8:16 ` Jérémy Jean
0 siblings, 0 replies; 5+ messages in thread
From: Jérémy Jean @ 2026-10-05 8:16 UTC (permalink / raw)
To: subash.a.kasiviswanathan
Cc: 'Sean Tranchetti', netdev, linux-kernel, stable
On 2026-10-05 07:46, subash.a.kasiviswanathan@oss.qualcomm.com wrote:
>> -----Original Message-----
>> From: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
>> Sent: Sunday, October 4, 2026 2:32 PM
>> To: Subash Abhinov Kasiviswanathan
>> <subash.a.kasiviswanathan@oss.qualcomm.com>; Sean Tranchetti
>> <sean.tranchetti@oss.qualcomm.com>
>> Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Jérémy Jean
>> <Jeremy.Jean@oss.cyber.gouv.fr>; stable@vger.kernel.org
>> Subject: [PATCH net v2] net: qualcomm: rmnet: require real-netns admin
>> for
>> bridging
>>
>> An rmnet device keeps its link to the real device when moved to
>> another
>> network namespace. The bridge callbacks change the real port, but
>> rtnetlink
>> only checks CAP_NET_ADMIN in the slave device's namespace.
>>
>> Require CAP_NET_ADMIN in the real device's namespace before adding or
>> removing a bridge. Use the slave device's namespace for the
>> comparison, since
>> that is the namespace rtnetlink authorized.
>>
>> Fixes: 60d58f971c10 ("net: qualcomm: rmnet: Implement bridge mode")
>> Cc: stable@vger.kernel.org
>> Assisted-by: LLM
>> Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
>> ---
>>
>> Changes in v2, after Subash Abhinov's review:
>> - Add the teardown check and use slave_dev for both capability checks.
>>
>> v1: https://lore.kernel.org/all/20260821202845.4053530-2-
>> Jeremy.Jean@oss.cyber.gouv.fr/
>>
>> .../ethernet/qualcomm/rmnet/rmnet_config.c | 20
>> ++++++++++++++++++-
>> 1 file changed, 19 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
>> b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
>> index bed6f63facf2..62d7acb13e0c 100644
>> --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
>> +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
>> @@ -441,6 +441,13 @@ int rmnet_add_bridge(struct net_device
>> *rmnet_dev,
>> struct rmnet_port *port, *slave_port;
>> int err;
>>
>> + /* The rtnl path only checks CAP_NET_ADMIN against
>> dev_net(slave_dev),
>> + * but bridge mode below controls real_dev, which may live in
>> another
>> + * netns.
>> + */
>> + if (!rtnl_dev_link_net_capable(slave_dev, dev_net(real_dev)))
>> + return -EPERM;
>> +
>> port = rmnet_get_port_rtnl(real_dev);
>>
>> /* If there is more than one rmnet dev attached, its probably being
>> @@ -489,7 +496,18 @@ int rmnet_add_bridge(struct net_device
>> *rmnet_dev, int rmnet_del_bridge(struct net_device *rmnet_dev,
>> struct net_device *slave_dev)
>> {
>> - struct rmnet_port *port = rmnet_get_port_rtnl(slave_dev);
>> + struct rmnet_priv *priv = netdev_priv(rmnet_dev);
>> + struct net_device *real_dev = priv->real_dev;
>> + struct rmnet_port *port;
>> +
>> + /* The rtnl path only checks CAP_NET_ADMIN against
>> dev_net(slave_dev),
>> + * but bridge teardown also updates real_dev, which may live in
>> another
>> + * netns.
>> + */
>> + if (!rtnl_dev_link_net_capable(slave_dev, dev_net(real_dev)))
>> + return -EPERM;
>> +
>> + port = rmnet_get_port_rtnl(slave_dev);
>>
>> rmnet_unregister_bridge(port);
>>
>
> A similar patch was committed recently in net-next. Please refer to
> https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=26ee8cd69d46a14b37ba5e512084fe80d730127a
Thanks for the pointer.
I was too slow processing your feedbacks, but good that it is patched.
Regards,
Jérémy
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net v2] net: qualcomm: rmnet: require real-netns admin for bridging
2026-10-04 20:31 [PATCH net v2] net: qualcomm: rmnet: require real-netns admin for bridging Jérémy Jean
2026-10-04 20:33 ` netdev-bot+sinfo
2026-10-05 5:46 ` subash.a.kasiviswanathan
@ 2026-10-05 21:06 ` netdev-bot+sashiko
2 siblings, 0 replies; 5+ messages in thread
From: netdev-bot+sashiko @ 2026-10-05 21:06 UTC (permalink / raw)
To: Jeremy.Jean
Cc: subash.a.kasiviswanathan, sean.tranchetti, netdev, linux-kernel,
stable, kuba
Thank you for your contribution! Sashiko AI review found 2 potential
issue(s) to consider.
Critical: 0 · High: 1 · Medium: 1 · Low: 0
If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).
- [High] The patch closes the cross-netns real-port privilege gap only in
the bridge ndo callbacks.
- [Medium] The commit message says it will 'Require CAP_NET_ADMIN in the
real device's namespace before ... removing a bridge'.
--
net: qualcomm: rmnet: require real-netns admin for bridging
An rmnet device keeps its link to the real device after it is moved to
another network namespace. This patch adds rtnl_dev_link_net_capable()
checks to rmnet_add_bridge() and rmnet_del_bridge(). With the checks,
changing the bridge state of the real port needs CAP_NET_ADMIN in the
real device's namespace.
> diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
> index bed6f63facf25..62d7acb13e0c0 100644
> --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
> +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
> @@ -441,6 +441,13 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
> struct rmnet_port *port, *slave_port;
> int err;
>
> + /* The rtnl path only checks CAP_NET_ADMIN against dev_net(slave_dev),
> + * but bridge mode below controls real_dev, which may live in another
> + * netns.
> + */
> + if (!rtnl_dev_link_net_capable(slave_dev, dev_net(real_dev)))
> + return -EPERM;
> +
[Severity: High]
The bridge ops are not the only rtnl entry point that modifies the shared
real port. Should rmnet_changelink() get the same check?
rmnet_changelink() looks up the port shared by every rmnet endpoint on
real_dev and modifies it. The only capability check is the one rtnetlink
does in dev_net(dev):
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c:rmnet_changelink() {
...
port = rmnet_get_port_rtnl(real_dev);
if (data[IFLA_RMNET_MUX_ID]) {
...
hlist_del_init_rcu(&ep->hlnode);
hlist_add_head_rcu(&ep->hlnode,
&port->muxed_ep[mux_id]);
...
}
if (data[IFLA_RMNET_FLAGS]) {
...
port->data_format &= ~flags->mask;
port->data_format |= flags->flags & flags->mask;
if (rmnet_vnd_update_dev_mtu(port, real_dev)) {
...
}
Suppose an rmnet device has been moved into netns B while real_dev stays
in netns A. A user with CAP_NET_ADMIN only in B can then send
RTM_NEWLINK with IFLA_RMNET_FLAGS. That rewrites port->data_format,
which controls deaggregation, MAP checksum offload and MAPv5 handling
for every rmnet endpoint on real_dev in A.
The same user can also move the endpoint between port->muxed_ep[]
buckets by changing IFLA_RMNET_MUX_ID.
rmnet_vnd_update_dev_mtu() walks every endpoint on the port and calls
rmnet_vnd_change_mtu(ep->egress_dev, real_dev->mtu - headroom). So
setting a flag that grows the headroom, such as
RMNET_FLAGS_EGRESS_MAP_CKSUMV4, also shrinks the MTU of rmnet devices
in netns A.
macvlan_changelink() already guards shared lower-port settings with:
!rtnl_dev_link_net_capable(dev, dev_net(vlan->lowerdev))
Would a similar guard in rmnet_changelink(), at least for
IFLA_RMNET_FLAGS and IFLA_RMNET_MUX_ID, be needed for this fix to be
complete? The other option would be to mark rmnet devices
netns_immutable.
> port = rmnet_get_port_rtnl(real_dev);
>
> /* If there is more than one rmnet dev attached, its probably being
> @@ -489,7 +496,18 @@ int rmnet_add_bridge(struct net_device *rmnet_dev,
> int rmnet_del_bridge(struct net_device *rmnet_dev,
> struct net_device *slave_dev)
> {
> - struct rmnet_port *port = rmnet_get_port_rtnl(slave_dev);
> + struct rmnet_priv *priv = netdev_priv(rmnet_dev);
> + struct net_device *real_dev = priv->real_dev;
> + struct rmnet_port *port;
> +
> + /* The rtnl path only checks CAP_NET_ADMIN against dev_net(slave_dev),
> + * but bridge teardown also updates real_dev, which may live in another
> + * netns.
> + */
> + if (!rtnl_dev_link_net_capable(slave_dev, dev_net(real_dev)))
> + return -EPERM;
[Severity: Medium]
The commit message says:
Require CAP_NET_ADMIN in the real device's namespace before adding or
removing a bridge.
This check gates only the ndo_del_slave path. Two other teardown paths
reach rmnet_unregister_bridge() and make the same real port change:
real_port->bridge_ep = NULL;
real_port->rmnet_mode = RMNET_EPMODE_VND;
The first is RTM_DELLINK on the rmnet device. rtnl_delete_link() calls
ops->dellink directly:
rtnl_delete_link()->rmnet_dellink() {
...
bridge_dev = real_port->bridge_ep;
if (bridge_dev) {
bridge_port = rmnet_get_port_rtnl(bridge_dev);
rmnet_unregister_bridge(bridge_port);
}
...
}
The second is NETDEV_UNREGISTER on the slave, which fires when a
virtual slave is deleted or moved to another netns:
rmnet_config_notify_cb()->rmnet_force_unassociate_device() {
...
} else {
rmnet_unregister_bridge(port);
}
}
Neither path has a real-netns capability check. Both are void or
notifier paths, so they cannot fail the same way.
A user who is admin only in the rmnet/slave netns would now get -EPERM
from "ip link set slave nomaster" or from a master change. In that case
do_set_master() returns after ndo_del_slave fails, before it attaches the
new master. The same user can still remove the bridge without
real-netns privilege by deleting the rmnet device, or the slave if it is
virtual.
Does the del-side check give any real protection here? The add-side
check already blocks unprivileged bridge creation. Would it make sense
to drop or rethink this check rather than block the clean unenslave
path?
> +
> + port = rmnet_get_port_rtnl(slave_dev);
>
> rmnet_unregister_bridge(port);
>
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261004203149.3042491-2-Jeremy.Jean%40oss.cyber.gouv.fr
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-05 21:06 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-04 20:31 [PATCH net v2] net: qualcomm: rmnet: require real-netns admin for bridging Jérémy Jean
2026-10-04 20:33 ` netdev-bot+sinfo
2026-10-05 5:46 ` subash.a.kasiviswanathan
2026-10-05 8:16 ` Jérémy Jean
2026-10-05 21:06 ` netdev-bot+sashiko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®