Skip to content

Commit 0015278

Browse files
committed
net: bridge: mcast: update multicast contex when vlan state is changed
jira VULN-162934 cve-pre CVE-2025-38248 commit-author Yong Wang <yongwang@nvidia.com> commit 6c13104 When the vlan STP state is changed, which could be manipulated by "bridge vlan" commands, similar to port STP state, this also impacts multicast behaviors such as igmp query. In the scenario of per-VLAN snooping, there's a need to update the corresponding multicast context to re-arm the port query timer when vlan state becomes "forwarding" etc. Update br_vlan_set_state() function to enable vlan multicast context in such scenario. Before the patch, the IGMP query does not happen in the last step of the following test sequence, i.e. no growth for tx counter: # ip link add name br1 up type bridge vlan_filtering 1 mcast_snooping 1 mcast_vlan_snooping 1 mcast_querier 1 mcast_stats_enabled 1 # bridge vlan global set vid 1 dev br1 mcast_snooping 1 mcast_querier 1 mcast_query_interval 100 mcast_startup_query_count 0 # ip link add name swp1 up master br1 type dummy # sleep 1 # bridge vlan set vid 1 dev swp1 state 4 # ip -j -p stats show dev swp1 group xstats_slave subgroup bridge suite mcast | jq '.[]["multicast"]["igmp_queries"]["tx_v2"]' 1 # sleep 1 # ip -j -p stats show dev swp1 group xstats_slave subgroup bridge suite mcast | jq '.[]["multicast"]["igmp_queries"]["tx_v2"]' 1 # bridge vlan set vid 1 dev swp1 state 3 # sleep 2 # ip -j -p stats show dev swp1 group xstats_slave subgroup bridge suite mcast | jq '.[]["multicast"]["igmp_queries"]["tx_v2"]' 1 After the patch, the IGMP query happens in the last step of the test: # ip link add name br1 up type bridge vlan_filtering 1 mcast_snooping 1 mcast_vlan_snooping 1 mcast_querier 1 mcast_stats_enabled 1 # bridge vlan global set vid 1 dev br1 mcast_snooping 1 mcast_querier 1 mcast_query_interval 100 mcast_startup_query_count 0 # ip link add name swp1 up master br1 type dummy # sleep 1 # bridge vlan set vid 1 dev swp1 state 4 # ip -j -p stats show dev swp1 group xstats_slave subgroup bridge suite mcast | jq '.[]["multicast"]["igmp_queries"]["tx_v2"]' 1 # sleep 1 # ip -j -p stats show dev swp1 group xstats_slave subgroup bridge suite mcast | jq '.[]["multicast"]["igmp_queries"]["tx_v2"]' 1 # bridge vlan set vid 1 dev swp1 state 3 # sleep 2 # ip -j -p stats show dev swp1 group xstats_slave subgroup bridge suite mcast | jq '.[]["multicast"]["igmp_queries"]["tx_v2"]' 3 Signed-off-by: Yong Wang <yongwang@nvidia.com> Reviewed-by: Andy Roulin <aroulin@nvidia.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: Petr Machata <petrm@nvidia.com> Acked-by: Nikolay Aleksandrov <razor@blackwall.org> Signed-off-by: David S. Miller <davem@davemloft.net> (cherry picked from commit 6c13104) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
1 parent 46144c2 commit 0015278

3 files changed

Lines changed: 38 additions & 3 deletions

File tree

net/bridge/br_mst.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ static void br_mst_vlan_set_state(struct net_bridge_vlan_group *vg,
8080
if (br_vlan_get_state(v) == state)
8181
return;
8282

83-
br_vlan_set_state(v, state);
84-
8583
if (v->vid == vg->pvid)
8684
br_vlan_set_pvid_state(vg, state);
85+
86+
br_vlan_set_state(v, state);
8787
}
8888

8989
int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,

net/bridge/br_multicast.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4272,6 +4272,32 @@ static void __br_multicast_stop(struct net_bridge_mcast *brmctx)
42724272
#endif
42734273
}
42744274

4275+
void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v, u8 state)
4276+
{
4277+
#if IS_ENABLED(CONFIG_BRIDGE_VLAN_FILTERING)
4278+
struct net_bridge *br;
4279+
4280+
if (!br_vlan_should_use(v))
4281+
return;
4282+
4283+
if (br_vlan_is_master(v))
4284+
return;
4285+
4286+
br = v->port->br;
4287+
4288+
if (!br_opt_get(br, BROPT_MCAST_VLAN_SNOOPING_ENABLED))
4289+
return;
4290+
4291+
if (br_vlan_state_allowed(state, true))
4292+
br_multicast_enable_port_ctx(&v->port_mcast_ctx);
4293+
4294+
/* Multicast is not disabled for the vlan when it goes in
4295+
* blocking state because the timers will expire and stop by
4296+
* themselves without sending more queries.
4297+
*/
4298+
#endif
4299+
}
4300+
42754301
void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on)
42764302
{
42774303
struct net_bridge *br;

net/bridge/br_private.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,7 @@ void br_multicast_port_ctx_init(struct net_bridge_port *port,
10521052
struct net_bridge_vlan *vlan,
10531053
struct net_bridge_mcast_port *pmctx);
10541054
void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx);
1055+
void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v, u8 state);
10551056
void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on);
10561057
int br_multicast_toggle_vlan_snooping(struct net_bridge *br, bool on,
10571058
struct netlink_ext_ack *extack);
@@ -1502,6 +1503,11 @@ static inline void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pm
15021503
{
15031504
}
15041505

1506+
static inline void br_multicast_update_vlan_mcast_ctx(struct net_bridge_vlan *v,
1507+
u8 state)
1508+
{
1509+
}
1510+
15051511
static inline void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan,
15061512
bool on)
15071513
{
@@ -1852,7 +1858,9 @@ bool br_vlan_global_opts_can_enter_range(const struct net_bridge_vlan *v_curr,
18521858
bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range,
18531859
const struct net_bridge_vlan *v_opts);
18541860

1855-
/* vlan state manipulation helpers using *_ONCE to annotate lock-free access */
1861+
/* vlan state manipulation helpers using *_ONCE to annotate lock-free access,
1862+
* while br_vlan_set_state() may access data protected by multicast_lock.
1863+
*/
18561864
static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v)
18571865
{
18581866
return READ_ONCE(v->state);
@@ -1861,6 +1869,7 @@ static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v)
18611869
static inline void br_vlan_set_state(struct net_bridge_vlan *v, u8 state)
18621870
{
18631871
WRITE_ONCE(v->state, state);
1872+
br_multicast_update_vlan_mcast_ctx(v, state);
18641873
}
18651874

18661875
static inline u8 br_vlan_get_pvid_state(const struct net_bridge_vlan_group *vg)

0 commit comments

Comments
 (0)