Commit 9ed973cc40c588abeaa58aea0683ea665132d11d

Authored by Linus Lüssing
Committed by David S. Miller
1 parent c3f9b01849

bridge: multicast: add sanity check for general query destination

General IGMP and MLD queries are supposed to have the multicast
link-local all-nodes address as their destination according to RFC2236
section 9, RFC3376 section 4.1.12/9.1, RFC2710 section 8 and RFC3810
section 5.1.15.

Without this check, such malformed IGMP/MLD queries can result in a
denial of service: The queries are ignored by most IGMP/MLD listeners
therefore they will not respond with an IGMP/MLD report. However,
without this patch these malformed MLD queries would enable the
snooping part in the bridge code, potentially shutting down the
according ports towards these hosts for multicast traffic as the
bridge did not learn about these listeners.

Reported-by: Jan Stancek <jstancek@redhat.com>
Signed-off-by: Linus Lüssing <linus.luessing@web.de>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 19 additions and 0 deletions Side-by-side Diff

net/bridge/br_multicast.c
... ... @@ -1181,6 +1181,14 @@
1181 1181 IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1;
1182 1182 }
1183 1183  
  1184 + /* RFC2236+RFC3376 (IGMPv2+IGMPv3) require the multicast link layer
  1185 + * all-systems destination addresses (224.0.0.1) for general queries
  1186 + */
  1187 + if (!group && iph->daddr != htonl(INADDR_ALLHOSTS_GROUP)) {
  1188 + err = -EINVAL;
  1189 + goto out;
  1190 + }
  1191 +
1184 1192 br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr,
1185 1193 max_delay);
1186 1194  
... ... @@ -1228,6 +1236,7 @@
1228 1236 unsigned long max_delay;
1229 1237 unsigned long now = jiffies;
1230 1238 const struct in6_addr *group = NULL;
  1239 + bool is_general_query;
1231 1240 int err = 0;
1232 1241  
1233 1242 spin_lock(&br->multicast_lock);
... ... @@ -1260,6 +1269,16 @@
1260 1269 group = &mld2q->mld2q_mca;
1261 1270  
1262 1271 max_delay = max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL);
  1272 + }
  1273 +
  1274 + is_general_query = group && ipv6_addr_any(group);
  1275 +
  1276 + /* RFC2710+RFC3810 (MLDv1+MLDv2) require the multicast link layer
  1277 + * all-nodes destination address (ff02::1) for general queries
  1278 + */
  1279 + if (is_general_query && !ipv6_addr_is_ll_all_nodes(&ip6h->daddr)) {
  1280 + err = -EINVAL;
  1281 + goto out;
1263 1282 }
1264 1283  
1265 1284 br_multicast_query_received(br, port, &br->ip6_querier,