Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Nikolay Aleksandrov and committed by
David S. Miller
54cb4319 524df92c

+9 -5
+9 -5
net/bridge/br_multicast.c
··· 2827 2827 #endif 2828 2828 2829 2829 static bool br_ip4_multicast_select_querier(struct net_bridge_mcast *brmctx, 2830 - struct net_bridge_port *port, 2830 + struct net_bridge_mcast_port *pmctx, 2831 2831 __be32 saddr) 2832 2832 { 2833 + struct net_bridge_port *port = pmctx ? pmctx->port : NULL; 2834 + 2833 2835 if (!timer_pending(&brmctx->ip4_own_query.timer) && 2834 2836 !timer_pending(&brmctx->ip4_other_query.timer)) 2835 2837 goto update; ··· 2855 2853 2856 2854 #if IS_ENABLED(CONFIG_IPV6) 2857 2855 static bool br_ip6_multicast_select_querier(struct net_bridge_mcast *brmctx, 2858 - struct net_bridge_port *port, 2856 + struct net_bridge_mcast_port *pmctx, 2859 2857 struct in6_addr *saddr) 2860 2858 { 2859 + struct net_bridge_port *port = pmctx ? pmctx->port : NULL; 2860 + 2861 2861 if (!timer_pending(&brmctx->ip6_own_query.timer) && 2862 2862 !timer_pending(&brmctx->ip6_other_query.timer)) 2863 2863 goto update; ··· 3080 3076 struct br_ip *saddr, 3081 3077 unsigned long max_delay) 3082 3078 { 3083 - if (!br_ip4_multicast_select_querier(brmctx, pmctx->port, saddr->src.ip4)) 3079 + if (!br_ip4_multicast_select_querier(brmctx, pmctx, saddr->src.ip4)) 3084 3080 return; 3085 3081 3086 3082 br_multicast_update_query_timer(brmctx, query, max_delay); ··· 3095 3091 struct br_ip *saddr, 3096 3092 unsigned long max_delay) 3097 3093 { 3098 - if (!br_ip6_multicast_select_querier(brmctx, pmctx->port, &saddr->src.ip6)) 3094 + if (!br_ip6_multicast_select_querier(brmctx, pmctx, &saddr->src.ip6)) 3099 3095 return; 3100 3096 3101 3097 br_multicast_update_query_timer(brmctx, query, max_delay); ··· 3326 3322 mod_timer(&own_query->timer, time); 3327 3323 3328 3324 for (p = mlock_dereference(mp->ports, brmctx->br); 3329 - p != NULL; 3325 + p != NULL && pmctx != NULL; 3330 3326 p = mlock_dereference(p->next, brmctx->br)) { 3331 3327 if (!br_port_group_equal(p, pmctx->port, src)) 3332 3328 continue;