kernel: fix crashes in bridge offload code
authorFelix Fietkau <nbd@nbd.name>
Tue, 31 May 2022 12:01:21 +0000 (14:01 +0200)
committerFelix Fietkau <nbd@nbd.name>
Thu, 2 Jun 2022 19:31:57 +0000 (21:31 +0200)
- fix an issues when accessing the port pointer of an expired/invalid fdb entry

Signed-off-by: Felix Fietkau <nbd@nbd.name>
target/linux/generic/hack-5.10/600-bridge_offload.patch
target/linux/generic/hack-5.15/600-bridge_offload.patch

index 586353816c2edf33d77e75f7cf012db72fda9d39..7e1b852bf308c1434303920007fe6d2b5c85b567 100644 (file)
 +      vg = nbp_vlan_group_rcu(inp);
 +      vlan = cb->input_vlan_present ? cb->input_vlan_tag : br_get_pvid(vg);
 +      fdb_in = br_fdb_find_rcu(p->br, eth_hdr(skb)->h_source, vlan);
-+      if (!fdb_in)
++      if (!fdb_in || !fdb_in->dst)
 +              goto out;
 +
 +      vg = nbp_vlan_group_rcu(p);
 +      vlan = skb_vlan_tag_present(skb) ? skb_vlan_tag_get_id(skb) : br_get_pvid(vg);
 +      fdb_out = br_fdb_find_rcu(p->br, eth_hdr(skb)->h_dest, vlan);
-+      if (!fdb_out)
++      if (!fdb_out || !fdb_out->dst)
 +              goto out;
 +
 +      br_offload_prepare_key(p, &key, skb);
 +#endif
 +
 +      flow = kmem_cache_alloc(offload_cache, GFP_ATOMIC);
-+      flow->port = fdb_in->dst;
++      flow->port = inp;
 +      memcpy(&flow->key, &key, sizeof(key));
 +
 +#ifdef CONFIG_BRIDGE_VLAN_FILTERING
 +      spin_lock_bh(&offload_lock);
 +      if (!o->enabled ||
 +          atomic_read(&p->offload.rht.nelems) >= p->br->offload_cache_size ||
-+          rhashtable_insert_fast(&flow->port->offload.rht, &flow->node, flow_params)) {
++          rhashtable_insert_fast(&inp->offload.rht, &flow->node, flow_params)) {
 +              kmem_cache_free(offload_cache, flow);
 +              goto out_unlock;
 +      }
 +#ifdef CONFIG_BRIDGE_VLAN_FILTERING
 +              cb->input_vlan_present = key.vlan_present != 0;
 +              cb->input_vlan_tag = key.vlan_tag;
-+              cb->input_ifindex = p->dev->ifindex;
 +#endif
++              cb->input_ifindex = p->dev->ifindex;
 +              goto out;
 +      }
 +
index c7942a0aefc2cf438fcbb1a8c44bfc4a66b0cff7..b396d748b65a407babf5df9481e75224ef1bddcd 100644 (file)
 +      vg = nbp_vlan_group_rcu(inp);
 +      vlan = cb->input_vlan_present ? cb->input_vlan_tag : br_get_pvid(vg);
 +      fdb_in = br_fdb_find_rcu(p->br, eth_hdr(skb)->h_source, vlan);
-+      if (!fdb_in)
++      if (!fdb_in || !fdb_in->dst)
 +              goto out;
 +
 +      vg = nbp_vlan_group_rcu(p);
 +      vlan = skb_vlan_tag_present(skb) ? skb_vlan_tag_get_id(skb) : br_get_pvid(vg);
 +      fdb_out = br_fdb_find_rcu(p->br, eth_hdr(skb)->h_dest, vlan);
-+      if (!fdb_out)
++      if (!fdb_out || !fdb_out->dst)
 +              goto out;
 +
 +      br_offload_prepare_key(p, &key, skb);
 +#endif
 +
 +      flow = kmem_cache_alloc(offload_cache, GFP_ATOMIC);
-+      flow->port = fdb_in->dst;
++      flow->port = inp;
 +      memcpy(&flow->key, &key, sizeof(key));
 +
 +#ifdef CONFIG_BRIDGE_VLAN_FILTERING
 +      spin_lock_bh(&offload_lock);
 +      if (!o->enabled ||
 +          atomic_read(&p->offload.rht.nelems) >= p->br->offload_cache_size ||
-+          rhashtable_insert_fast(&flow->port->offload.rht, &flow->node, flow_params)) {
++          rhashtable_insert_fast(&inp->offload.rht, &flow->node, flow_params)) {
 +              kmem_cache_free(offload_cache, flow);
 +              goto out_unlock;
 +      }
 +#ifdef CONFIG_BRIDGE_VLAN_FILTERING
 +              cb->input_vlan_present = key.vlan_present != 0;
 +              cb->input_vlan_tag = key.vlan_tag;
-+              cb->input_ifindex = p->dev->ifindex;
 +#endif
++              cb->input_ifindex = p->dev->ifindex;
 +              goto out;
 +      }
 +