summaryrefslogtreecommitdiff
path: root/net/bridge
diff options
context:
space:
mode:
authorNikolay Aleksandrov <nikolay@nvidia.com>2021-07-21 13:06:24 +0300
committerDavid S. Miller <davem@davemloft.net>2021-07-21 09:04:03 -0700
commit54cb43199e14c1181ddcd4a3782f1f7eb56bdab8 (patch)
tree2ed34b06307271aceb991f25e54e36a17f189973 /net/bridge
parent524df92c1907d31bc2d2643e81c680381d7c6bf8 (diff)
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: adc47037a7d5 ("net: bridge: multicast: use multicast contexts instead of bridge or port") Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_multicast.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 976491951c82..214d1bf854ad 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -2827,9 +2827,11 @@ unlock_continue:
#endif
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)
{
+ struct net_bridge_port *port = pmctx ? pmctx->port : NULL;
+
if (!timer_pending(&brmctx->ip4_own_query.timer) &&
!timer_pending(&brmctx->ip4_other_query.timer))
goto update;
@@ -2853,9 +2855,11 @@ update:
#if IS_ENABLED(CONFIG_IPV6)
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 net_bridge_port *port = pmctx ? pmctx->port : NULL;
+
if (!timer_pending(&brmctx->ip6_own_query.timer) &&
!timer_pending(&brmctx->ip6_other_query.timer))
goto update;
@@ -3076,7 +3080,7 @@ br_ip4_multicast_query_received(struct net_bridge_mcast *brmctx,
struct br_ip *saddr,
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;
br_multicast_update_query_timer(brmctx, query, max_delay);
@@ -3091,7 +3095,7 @@ br_ip6_multicast_query_received(struct net_bridge_mcast *brmctx,
struct br_ip *saddr,
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;
br_multicast_update_query_timer(brmctx, query, max_delay);
@@ -3322,7 +3326,7 @@ br_multicast_leave_group(struct net_bridge_mcast *brmctx,
mod_timer(&own_query->timer, time);
for (p = mlock_dereference(mp->ports, brmctx->br);
- p != NULL;
+ p != NULL && pmctx != NULL;
p = mlock_dereference(p->next, brmctx->br)) {
if (!br_port_group_equal(p, pmctx->port, src))
continue;