Commit 54cb4319 authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by David S. Miller

net: bridge: multicast: fix igmp/mld port context null pointer dereferences

With the recent change to use bridge/port multicast context pointers
instead of bridge/port I missed to convert two locations which pass the
port pointer as-is, but with the new model we need to verify the port
context is non-NULL first and retrieve the port from it. The first
location is when doing querier selection when a query is received, the
second location is when leaving a group. The port context will be null
if the packets originated from the bridge device (i.e. from the host).
The fix is simple just check if the port context exists and retrieve
the port pointer from it.

Fixes: adc47037 ("net: bridge: multicast: use multicast contexts instead of bridge or port")
Signed-off-by: default avatarNikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 524df92c
...@@ -2827,9 +2827,11 @@ static int br_ip6_multicast_mld2_report(struct net_bridge_mcast *brmctx, ...@@ -2827,9 +2827,11 @@ static int br_ip6_multicast_mld2_report(struct net_bridge_mcast *brmctx,
#endif #endif
static bool br_ip4_multicast_select_querier(struct net_bridge_mcast *brmctx, static bool br_ip4_multicast_select_querier(struct net_bridge_mcast *brmctx,
struct net_bridge_port *port, struct net_bridge_mcast_port *pmctx,
__be32 saddr) __be32 saddr)
{ {
struct net_bridge_port *port = pmctx ? pmctx->port : NULL;
if (!timer_pending(&brmctx->ip4_own_query.timer) && if (!timer_pending(&brmctx->ip4_own_query.timer) &&
!timer_pending(&brmctx->ip4_other_query.timer)) !timer_pending(&brmctx->ip4_other_query.timer))
goto update; goto update;
...@@ -2853,9 +2855,11 @@ static bool br_ip4_multicast_select_querier(struct net_bridge_mcast *brmctx, ...@@ -2853,9 +2855,11 @@ static bool br_ip4_multicast_select_querier(struct net_bridge_mcast *brmctx,
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
static bool br_ip6_multicast_select_querier(struct net_bridge_mcast *brmctx, static bool br_ip6_multicast_select_querier(struct net_bridge_mcast *brmctx,
struct net_bridge_port *port, struct net_bridge_mcast_port *pmctx,
struct in6_addr *saddr) struct in6_addr *saddr)
{ {
struct net_bridge_port *port = pmctx ? pmctx->port : NULL;
if (!timer_pending(&brmctx->ip6_own_query.timer) && if (!timer_pending(&brmctx->ip6_own_query.timer) &&
!timer_pending(&brmctx->ip6_other_query.timer)) !timer_pending(&brmctx->ip6_other_query.timer))
goto update; goto update;
...@@ -3076,7 +3080,7 @@ br_ip4_multicast_query_received(struct net_bridge_mcast *brmctx, ...@@ -3076,7 +3080,7 @@ br_ip4_multicast_query_received(struct net_bridge_mcast *brmctx,
struct br_ip *saddr, struct br_ip *saddr,
unsigned long max_delay) unsigned long max_delay)
{ {
if (!br_ip4_multicast_select_querier(brmctx, pmctx->port, saddr->src.ip4)) if (!br_ip4_multicast_select_querier(brmctx, pmctx, saddr->src.ip4))
return; return;
br_multicast_update_query_timer(brmctx, query, max_delay); br_multicast_update_query_timer(brmctx, query, max_delay);
...@@ -3091,7 +3095,7 @@ br_ip6_multicast_query_received(struct net_bridge_mcast *brmctx, ...@@ -3091,7 +3095,7 @@ br_ip6_multicast_query_received(struct net_bridge_mcast *brmctx,
struct br_ip *saddr, struct br_ip *saddr,
unsigned long max_delay) unsigned long max_delay)
{ {
if (!br_ip6_multicast_select_querier(brmctx, pmctx->port, &saddr->src.ip6)) if (!br_ip6_multicast_select_querier(brmctx, pmctx, &saddr->src.ip6))
return; return;
br_multicast_update_query_timer(brmctx, query, max_delay); br_multicast_update_query_timer(brmctx, query, max_delay);
...@@ -3322,7 +3326,7 @@ br_multicast_leave_group(struct net_bridge_mcast *brmctx, ...@@ -3322,7 +3326,7 @@ br_multicast_leave_group(struct net_bridge_mcast *brmctx,
mod_timer(&own_query->timer, time); mod_timer(&own_query->timer, time);
for (p = mlock_dereference(mp->ports, brmctx->br); for (p = mlock_dereference(mp->ports, brmctx->br);
p != NULL; p != NULL && pmctx != NULL;
p = mlock_dereference(p->next, brmctx->br)) { p = mlock_dereference(p->next, brmctx->br)) {
if (!br_port_group_equal(p, pmctx->port, src)) if (!br_port_group_equal(p, pmctx->port, src))
continue; continue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment