* [PATCH net v2 0/2] net: bridge: fix two MST bugs
@ 2025-11-05 11:19 Nikolay Aleksandrov
2025-11-05 11:19 ` [PATCH net v2 1/2] net: bridge: fix use-after-free due to MST port state bypass Nikolay Aleksandrov
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Nikolay Aleksandrov @ 2025-11-05 11:19 UTC (permalink / raw)
To: netdev
Cc: tobias, idosch, kuba, davem, bridge, pabeni, edumazet, horms,
petrm, Nikolay Aleksandrov
Hi,
Patch 01 fixes a race condition that exists between expired fdb deletion
and port deletion when MST is enabled. Learning can happen after the
port's state has been changed to disabled which could lead to that
port's memory being used after it's been freed. The issue was reported
by syzbot, more information in patch 01. Patch 02 fixes an issue with
MST's static key which Ido spotted, we can have multiple bridges with MST
and a single bridge can erroneously disable it for all.
v2: dropped the selftest as it is useless with the new fix
patch 01 - new fix approach relying on port's vlan group
patch 02 - new patch fixing an issue with MST's static key
Thanks,
Nik
Nikolay Aleksandrov (2):
net: bridge: fix use-after-free due to MST port state bypass
net: bridge: fix MST static key usage
net/bridge/br_forward.c | 2 +-
net/bridge/br_if.c | 1 +
net/bridge/br_input.c | 4 ++--
net/bridge/br_mst.c | 10 ++++++++--
net/bridge/br_private.h | 13 ++++++++++---
5 files changed, 22 insertions(+), 8 deletions(-)
--
2.51.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH net v2 1/2] net: bridge: fix use-after-free due to MST port state bypass
2025-11-05 11:19 [PATCH net v2 0/2] net: bridge: fix two MST bugs Nikolay Aleksandrov
@ 2025-11-05 11:19 ` Nikolay Aleksandrov
2025-11-05 16:59 ` Ido Schimmel
2025-11-05 11:19 ` [PATCH net v2 2/2] net: bridge: fix MST static key usage Nikolay Aleksandrov
2025-11-06 15:40 ` [PATCH net v2 0/2] net: bridge: fix two MST bugs patchwork-bot+netdevbpf
2 siblings, 1 reply; 6+ messages in thread
From: Nikolay Aleksandrov @ 2025-11-05 11:19 UTC (permalink / raw)
To: netdev
Cc: tobias, idosch, kuba, davem, bridge, pabeni, edumazet, horms,
petrm, Nikolay Aleksandrov, syzbot+dd280197f0f7ab3917be
syzbot reported[1] a use-after-free when deleting an expired fdb. It is
due to a race condition between learning still happening and a port being
deleted, after all its fdbs have been flushed. The port's state has been
toggled to disabled so no learning should happen at that time, but if we
have MST enabled, it will bypass the port's state, that together with VLAN
filtering disabled can lead to fdb learning at a time when it shouldn't
happen while the port is being deleted. VLAN filtering must be disabled
because we flush the port VLANs when it's being deleted which will stop
learning. This fix adds a check for the port's vlan group which is
initialized to NULL when the port is getting deleted, that avoids the port
state bypass. When MST is enabled there would be a minimal new overhead
in the fast-path because the port's vlan group pointer is cache-hot.
[1] https://syzkaller.appspot.com/bug?extid=dd280197f0f7ab3917be
Fixes: ec7328b59176 ("net: bridge: mst: Multiple Spanning Tree (MST) mode")
Reported-by: syzbot+dd280197f0f7ab3917be@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/69088ffa.050a0220.29fc44.003d.GAE@google.com/
Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
---
v2: new fix approach using port's vlan group check when MST is enabled
we rely on the fact that the vlan group gets initialized to NULL
when the port is getting deleted
net/bridge/br_forward.c | 2 +-
net/bridge/br_input.c | 4 ++--
net/bridge/br_private.h | 8 +++++---
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 870bdf2e082c..dea09096ad0f 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -25,7 +25,7 @@ static inline int should_deliver(const struct net_bridge_port *p,
vg = nbp_vlan_group_rcu(p);
return ((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
- (br_mst_is_enabled(p->br) || p->state == BR_STATE_FORWARDING) &&
+ (br_mst_is_enabled(p) || p->state == BR_STATE_FORWARDING) &&
br_allowed_egress(vg, skb) && nbp_switchdev_allowed_egress(p, skb) &&
!br_skb_isolated(p, skb);
}
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 67b4c905e49a..777fa869c1a1 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -94,7 +94,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
br = p->br;
- if (br_mst_is_enabled(br)) {
+ if (br_mst_is_enabled(p)) {
state = BR_STATE_FORWARDING;
} else {
if (p->state == BR_STATE_DISABLED) {
@@ -429,7 +429,7 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
return RX_HANDLER_PASS;
forward:
- if (br_mst_is_enabled(p->br))
+ if (br_mst_is_enabled(p))
goto defer_stp_filtering;
switch (p->state) {
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 16be5d250402..b571d6f61389 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1935,10 +1935,12 @@ static inline bool br_vlan_state_allowed(u8 state, bool learn_allow)
/* br_mst.c */
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
DECLARE_STATIC_KEY_FALSE(br_mst_used);
-static inline bool br_mst_is_enabled(struct net_bridge *br)
+static inline bool br_mst_is_enabled(const struct net_bridge_port *p)
{
+ /* check the port's vlan group to avoid racing with port deletion */
return static_branch_unlikely(&br_mst_used) &&
- br_opt_get(br, BROPT_MST_ENABLED);
+ br_opt_get(p->br, BROPT_MST_ENABLED) &&
+ rcu_access_pointer(p->vlgrp);
}
int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,
@@ -1953,7 +1955,7 @@ int br_mst_fill_info(struct sk_buff *skb,
int br_mst_process(struct net_bridge_port *p, const struct nlattr *mst_attr,
struct netlink_ext_ack *extack);
#else
-static inline bool br_mst_is_enabled(struct net_bridge *br)
+static inline bool br_mst_is_enabled(const struct net_bridge_port *p)
{
return false;
}
--
2.51.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH net v2 2/2] net: bridge: fix MST static key usage
2025-11-05 11:19 [PATCH net v2 0/2] net: bridge: fix two MST bugs Nikolay Aleksandrov
2025-11-05 11:19 ` [PATCH net v2 1/2] net: bridge: fix use-after-free due to MST port state bypass Nikolay Aleksandrov
@ 2025-11-05 11:19 ` Nikolay Aleksandrov
2025-11-05 17:04 ` Ido Schimmel
2025-11-06 15:40 ` [PATCH net v2 0/2] net: bridge: fix two MST bugs patchwork-bot+netdevbpf
2 siblings, 1 reply; 6+ messages in thread
From: Nikolay Aleksandrov @ 2025-11-05 11:19 UTC (permalink / raw)
To: netdev
Cc: tobias, idosch, kuba, davem, bridge, pabeni, edumazet, horms,
petrm, Nikolay Aleksandrov
As Ido pointed out, the static key usage in MST is buggy and should use
inc/dec instead of enable/disable because we can have multiple bridges
with MST enabled which means a single bridge can disable MST for all.
Use static_branch_inc/dec to avoid that. When destroying a bridge decrement
the key if MST was enabled.
Fixes: ec7328b59176 ("net: bridge: mst: Multiple Spanning Tree (MST) mode")
Reported-by: Ido Schimmel <idosch@nvidia.com>
Closes: https://lore.kernel.org/netdev/20251104120313.1306566-1-razor@blackwall.org/T/#m6888d87658f94ed1725433940f4f4ebb00b5a68b
Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
---
v2: new fix
net/bridge/br_if.c | 1 +
net/bridge/br_mst.c | 10 ++++++++--
net/bridge/br_private.h | 5 +++++
3 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 98c5b9c3145f..ca3a637d7cca 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -386,6 +386,7 @@ void br_dev_delete(struct net_device *dev, struct list_head *head)
del_nbp(p);
}
+ br_mst_uninit(br);
br_recalculate_neigh_suppress_enabled(br);
br_fdb_delete_by_port(br, NULL, 0, 1);
diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c
index 3f24b4ee49c2..43a300ae6bfa 100644
--- a/net/bridge/br_mst.c
+++ b/net/bridge/br_mst.c
@@ -22,6 +22,12 @@ bool br_mst_enabled(const struct net_device *dev)
}
EXPORT_SYMBOL_GPL(br_mst_enabled);
+void br_mst_uninit(struct net_bridge *br)
+{
+ if (br_opt_get(br, BROPT_MST_ENABLED))
+ static_branch_dec(&br_mst_used);
+}
+
int br_mst_get_info(const struct net_device *dev, u16 msti, unsigned long *vids)
{
const struct net_bridge_vlan_group *vg;
@@ -225,9 +231,9 @@ int br_mst_set_enabled(struct net_bridge *br, bool on,
return err;
if (on)
- static_branch_enable(&br_mst_used);
+ static_branch_inc(&br_mst_used);
else
- static_branch_disable(&br_mst_used);
+ static_branch_dec(&br_mst_used);
br_opt_toggle(br, BROPT_MST_ENABLED, on);
return 0;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index b571d6f61389..7280c4e9305f 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1954,6 +1954,7 @@ int br_mst_fill_info(struct sk_buff *skb,
const struct net_bridge_vlan_group *vg);
int br_mst_process(struct net_bridge_port *p, const struct nlattr *mst_attr,
struct netlink_ext_ack *extack);
+void br_mst_uninit(struct net_bridge *br);
#else
static inline bool br_mst_is_enabled(const struct net_bridge_port *p)
{
@@ -1989,6 +1990,10 @@ static inline int br_mst_process(struct net_bridge_port *p,
{
return -EOPNOTSUPP;
}
+
+static inline void br_mst_uninit(struct net_bridge *br)
+{
+}
#endif
struct nf_br_ops {
--
2.51.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH net v2 1/2] net: bridge: fix use-after-free due to MST port state bypass
2025-11-05 11:19 ` [PATCH net v2 1/2] net: bridge: fix use-after-free due to MST port state bypass Nikolay Aleksandrov
@ 2025-11-05 16:59 ` Ido Schimmel
0 siblings, 0 replies; 6+ messages in thread
From: Ido Schimmel @ 2025-11-05 16:59 UTC (permalink / raw)
To: Nikolay Aleksandrov
Cc: netdev, tobias, kuba, davem, bridge, pabeni, edumazet, horms,
petrm, syzbot+dd280197f0f7ab3917be
On Wed, Nov 05, 2025 at 01:19:18PM +0200, Nikolay Aleksandrov wrote:
> syzbot reported[1] a use-after-free when deleting an expired fdb. It is
> due to a race condition between learning still happening and a port being
> deleted, after all its fdbs have been flushed. The port's state has been
> toggled to disabled so no learning should happen at that time, but if we
> have MST enabled, it will bypass the port's state, that together with VLAN
> filtering disabled can lead to fdb learning at a time when it shouldn't
> happen while the port is being deleted. VLAN filtering must be disabled
> because we flush the port VLANs when it's being deleted which will stop
> learning. This fix adds a check for the port's vlan group which is
> initialized to NULL when the port is getting deleted, that avoids the port
> state bypass. When MST is enabled there would be a minimal new overhead
> in the fast-path because the port's vlan group pointer is cache-hot.
>
> [1] https://syzkaller.appspot.com/bug?extid=dd280197f0f7ab3917be
>
> Fixes: ec7328b59176 ("net: bridge: mst: Multiple Spanning Tree (MST) mode")
> Reported-by: syzbot+dd280197f0f7ab3917be@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/netdev/69088ffa.050a0220.29fc44.003d.GAE@google.com/
> Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net v2 2/2] net: bridge: fix MST static key usage
2025-11-05 11:19 ` [PATCH net v2 2/2] net: bridge: fix MST static key usage Nikolay Aleksandrov
@ 2025-11-05 17:04 ` Ido Schimmel
0 siblings, 0 replies; 6+ messages in thread
From: Ido Schimmel @ 2025-11-05 17:04 UTC (permalink / raw)
To: Nikolay Aleksandrov
Cc: netdev, tobias, kuba, davem, bridge, pabeni, edumazet, horms,
petrm
On Wed, Nov 05, 2025 at 01:19:19PM +0200, Nikolay Aleksandrov wrote:
> As Ido pointed out, the static key usage in MST is buggy and should use
> inc/dec instead of enable/disable because we can have multiple bridges
> with MST enabled which means a single bridge can disable MST for all.
> Use static_branch_inc/dec to avoid that. When destroying a bridge decrement
> the key if MST was enabled.
>
> Fixes: ec7328b59176 ("net: bridge: mst: Multiple Spanning Tree (MST) mode")
> Reported-by: Ido Schimmel <idosch@nvidia.com>
> Closes: https://lore.kernel.org/netdev/20251104120313.1306566-1-razor@blackwall.org/T/#m6888d87658f94ed1725433940f4f4ebb00b5a68b
> Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH net v2 0/2] net: bridge: fix two MST bugs
2025-11-05 11:19 [PATCH net v2 0/2] net: bridge: fix two MST bugs Nikolay Aleksandrov
2025-11-05 11:19 ` [PATCH net v2 1/2] net: bridge: fix use-after-free due to MST port state bypass Nikolay Aleksandrov
2025-11-05 11:19 ` [PATCH net v2 2/2] net: bridge: fix MST static key usage Nikolay Aleksandrov
@ 2025-11-06 15:40 ` patchwork-bot+netdevbpf
2 siblings, 0 replies; 6+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-11-06 15:40 UTC (permalink / raw)
To: Nikolay Aleksandrov
Cc: netdev, tobias, idosch, kuba, davem, bridge, pabeni, edumazet,
horms, petrm
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 5 Nov 2025 13:19:17 +0200 you wrote:
> Hi,
> Patch 01 fixes a race condition that exists between expired fdb deletion
> and port deletion when MST is enabled. Learning can happen after the
> port's state has been changed to disabled which could lead to that
> port's memory being used after it's been freed. The issue was reported
> by syzbot, more information in patch 01. Patch 02 fixes an issue with
> MST's static key which Ido spotted, we can have multiple bridges with MST
> and a single bridge can erroneously disable it for all.
>
> [...]
Here is the summary with links:
- [net,v2,1/2] net: bridge: fix use-after-free due to MST port state bypass
https://git.kernel.org/netdev/net/c/8dca36978aa8
- [net,v2,2/2] net: bridge: fix MST static key usage
https://git.kernel.org/netdev/net/c/ee87c63f9b2a
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-11-06 15:40 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-05 11:19 [PATCH net v2 0/2] net: bridge: fix two MST bugs Nikolay Aleksandrov
2025-11-05 11:19 ` [PATCH net v2 1/2] net: bridge: fix use-after-free due to MST port state bypass Nikolay Aleksandrov
2025-11-05 16:59 ` Ido Schimmel
2025-11-05 11:19 ` [PATCH net v2 2/2] net: bridge: fix MST static key usage Nikolay Aleksandrov
2025-11-05 17:04 ` Ido Schimmel
2025-11-06 15:40 ` [PATCH net v2 0/2] net: bridge: fix two MST bugs patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).