Skip to content

Commit 13fef4f

Browse files
committed
Merge branch 'net-bridge-fix-two-mst-bugs'
Nikolay Aleksandrov says: ==================== net: bridge: fix two MST bugs 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. ==================== Link: https://patch.msgid.link/20251105111919.1499702-1-razor@blackwall.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 0216721 + ee87c63 commit 13fef4f

5 files changed

Lines changed: 22 additions & 8 deletions

File tree

net/bridge/br_forward.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ static inline int should_deliver(const struct net_bridge_port *p,
2525

2626
vg = nbp_vlan_group_rcu(p);
2727
return ((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
28-
(br_mst_is_enabled(p->br) || p->state == BR_STATE_FORWARDING) &&
28+
(br_mst_is_enabled(p) || p->state == BR_STATE_FORWARDING) &&
2929
br_allowed_egress(vg, skb) && nbp_switchdev_allowed_egress(p, skb) &&
3030
!br_skb_isolated(p, skb);
3131
}

net/bridge/br_if.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ void br_dev_delete(struct net_device *dev, struct list_head *head)
386386
del_nbp(p);
387387
}
388388

389+
br_mst_uninit(br);
389390
br_recalculate_neigh_suppress_enabled(br);
390391

391392
br_fdb_delete_by_port(br, NULL, 0, 1);

net/bridge/br_input.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
9494

9595
br = p->br;
9696

97-
if (br_mst_is_enabled(br)) {
97+
if (br_mst_is_enabled(p)) {
9898
state = BR_STATE_FORWARDING;
9999
} else {
100100
if (p->state == BR_STATE_DISABLED) {
@@ -429,7 +429,7 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
429429
return RX_HANDLER_PASS;
430430

431431
forward:
432-
if (br_mst_is_enabled(p->br))
432+
if (br_mst_is_enabled(p))
433433
goto defer_stp_filtering;
434434

435435
switch (p->state) {

net/bridge/br_mst.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ bool br_mst_enabled(const struct net_device *dev)
2222
}
2323
EXPORT_SYMBOL_GPL(br_mst_enabled);
2424

25+
void br_mst_uninit(struct net_bridge *br)
26+
{
27+
if (br_opt_get(br, BROPT_MST_ENABLED))
28+
static_branch_dec(&br_mst_used);
29+
}
30+
2531
int br_mst_get_info(const struct net_device *dev, u16 msti, unsigned long *vids)
2632
{
2733
const struct net_bridge_vlan_group *vg;
@@ -225,9 +231,9 @@ int br_mst_set_enabled(struct net_bridge *br, bool on,
225231
return err;
226232

227233
if (on)
228-
static_branch_enable(&br_mst_used);
234+
static_branch_inc(&br_mst_used);
229235
else
230-
static_branch_disable(&br_mst_used);
236+
static_branch_dec(&br_mst_used);
231237

232238
br_opt_toggle(br, BROPT_MST_ENABLED, on);
233239
return 0;

net/bridge/br_private.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,10 +1935,12 @@ static inline bool br_vlan_state_allowed(u8 state, bool learn_allow)
19351935
/* br_mst.c */
19361936
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
19371937
DECLARE_STATIC_KEY_FALSE(br_mst_used);
1938-
static inline bool br_mst_is_enabled(struct net_bridge *br)
1938+
static inline bool br_mst_is_enabled(const struct net_bridge_port *p)
19391939
{
1940+
/* check the port's vlan group to avoid racing with port deletion */
19401941
return static_branch_unlikely(&br_mst_used) &&
1941-
br_opt_get(br, BROPT_MST_ENABLED);
1942+
br_opt_get(p->br, BROPT_MST_ENABLED) &&
1943+
rcu_access_pointer(p->vlgrp);
19421944
}
19431945

19441946
int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,
@@ -1952,8 +1954,9 @@ int br_mst_fill_info(struct sk_buff *skb,
19521954
const struct net_bridge_vlan_group *vg);
19531955
int br_mst_process(struct net_bridge_port *p, const struct nlattr *mst_attr,
19541956
struct netlink_ext_ack *extack);
1957+
void br_mst_uninit(struct net_bridge *br);
19551958
#else
1956-
static inline bool br_mst_is_enabled(struct net_bridge *br)
1959+
static inline bool br_mst_is_enabled(const struct net_bridge_port *p)
19571960
{
19581961
return false;
19591962
}
@@ -1987,6 +1990,10 @@ static inline int br_mst_process(struct net_bridge_port *p,
19871990
{
19881991
return -EOPNOTSUPP;
19891992
}
1993+
1994+
static inline void br_mst_uninit(struct net_bridge *br)
1995+
{
1996+
}
19901997
#endif
19911998

19921999
struct nf_br_ops {

0 commit comments

Comments
 (0)