kernel: fix crashes in bridge offload code
- fix an issues when accessing the port pointer of an expired/invalid fdb entry Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
		| @@ -434,13 +434,13 @@ | |||||||
| +	vg = nbp_vlan_group_rcu(inp); | +	vg = nbp_vlan_group_rcu(inp); | ||||||
| +	vlan = cb->input_vlan_present ? cb->input_vlan_tag : br_get_pvid(vg); | +	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); | +	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; | +		goto out; | ||||||
| + | + | ||||||
| +	vg = nbp_vlan_group_rcu(p); | +	vg = nbp_vlan_group_rcu(p); | ||||||
| +	vlan = skb_vlan_tag_present(skb) ? skb_vlan_tag_get_id(skb) : br_get_pvid(vg); | +	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); | +	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; | +		goto out; | ||||||
| + | + | ||||||
| +	br_offload_prepare_key(p, &key, skb); | +	br_offload_prepare_key(p, &key, skb); | ||||||
| @@ -450,7 +450,7 @@ | |||||||
| +#endif | +#endif | ||||||
| + | + | ||||||
| +	flow = kmem_cache_alloc(offload_cache, GFP_ATOMIC); | +	flow = kmem_cache_alloc(offload_cache, GFP_ATOMIC); | ||||||
| +	flow->port = fdb_in->dst; | +	flow->port = inp; | ||||||
| +	memcpy(&flow->key, &key, sizeof(key)); | +	memcpy(&flow->key, &key, sizeof(key)); | ||||||
| + | + | ||||||
| +#ifdef CONFIG_BRIDGE_VLAN_FILTERING | +#ifdef CONFIG_BRIDGE_VLAN_FILTERING | ||||||
| @@ -465,7 +465,7 @@ | |||||||
| +	spin_lock_bh(&offload_lock); | +	spin_lock_bh(&offload_lock); | ||||||
| +	if (!o->enabled || | +	if (!o->enabled || | ||||||
| +	    atomic_read(&p->offload.rht.nelems) >= p->br->offload_cache_size || | +	    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); | +		kmem_cache_free(offload_cache, flow); | ||||||
| +		goto out_unlock; | +		goto out_unlock; | ||||||
| +	} | +	} | ||||||
| @@ -511,8 +511,8 @@ | |||||||
| +#ifdef CONFIG_BRIDGE_VLAN_FILTERING | +#ifdef CONFIG_BRIDGE_VLAN_FILTERING | ||||||
| +		cb->input_vlan_present = key.vlan_present != 0; | +		cb->input_vlan_present = key.vlan_present != 0; | ||||||
| +		cb->input_vlan_tag = key.vlan_tag; | +		cb->input_vlan_tag = key.vlan_tag; | ||||||
| +		cb->input_ifindex = p->dev->ifindex; |  | ||||||
| +#endif | +#endif | ||||||
|  | +		cb->input_ifindex = p->dev->ifindex; | ||||||
| +		goto out; | +		goto out; | ||||||
| +	} | +	} | ||||||
| + | + | ||||||
|   | |||||||
| @@ -434,13 +434,13 @@ | |||||||
| +	vg = nbp_vlan_group_rcu(inp); | +	vg = nbp_vlan_group_rcu(inp); | ||||||
| +	vlan = cb->input_vlan_present ? cb->input_vlan_tag : br_get_pvid(vg); | +	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); | +	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; | +		goto out; | ||||||
| + | + | ||||||
| +	vg = nbp_vlan_group_rcu(p); | +	vg = nbp_vlan_group_rcu(p); | ||||||
| +	vlan = skb_vlan_tag_present(skb) ? skb_vlan_tag_get_id(skb) : br_get_pvid(vg); | +	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); | +	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; | +		goto out; | ||||||
| + | + | ||||||
| +	br_offload_prepare_key(p, &key, skb); | +	br_offload_prepare_key(p, &key, skb); | ||||||
| @@ -450,7 +450,7 @@ | |||||||
| +#endif | +#endif | ||||||
| + | + | ||||||
| +	flow = kmem_cache_alloc(offload_cache, GFP_ATOMIC); | +	flow = kmem_cache_alloc(offload_cache, GFP_ATOMIC); | ||||||
| +	flow->port = fdb_in->dst; | +	flow->port = inp; | ||||||
| +	memcpy(&flow->key, &key, sizeof(key)); | +	memcpy(&flow->key, &key, sizeof(key)); | ||||||
| + | + | ||||||
| +#ifdef CONFIG_BRIDGE_VLAN_FILTERING | +#ifdef CONFIG_BRIDGE_VLAN_FILTERING | ||||||
| @@ -465,7 +465,7 @@ | |||||||
| +	spin_lock_bh(&offload_lock); | +	spin_lock_bh(&offload_lock); | ||||||
| +	if (!o->enabled || | +	if (!o->enabled || | ||||||
| +	    atomic_read(&p->offload.rht.nelems) >= p->br->offload_cache_size || | +	    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); | +		kmem_cache_free(offload_cache, flow); | ||||||
| +		goto out_unlock; | +		goto out_unlock; | ||||||
| +	} | +	} | ||||||
| @@ -511,8 +511,8 @@ | |||||||
| +#ifdef CONFIG_BRIDGE_VLAN_FILTERING | +#ifdef CONFIG_BRIDGE_VLAN_FILTERING | ||||||
| +		cb->input_vlan_present = key.vlan_present != 0; | +		cb->input_vlan_present = key.vlan_present != 0; | ||||||
| +		cb->input_vlan_tag = key.vlan_tag; | +		cb->input_vlan_tag = key.vlan_tag; | ||||||
| +		cb->input_ifindex = p->dev->ifindex; |  | ||||||
| +#endif | +#endif | ||||||
|  | +		cb->input_ifindex = p->dev->ifindex; | ||||||
| +		goto out; | +		goto out; | ||||||
| +	} | +	} | ||||||
| + | + | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Felix Fietkau
					Felix Fietkau