Skip to content

Commit fc92f74

Browse files
Vlad Yasevichdavem330
authored andcommitted
bridge: Fix crash with vlan filtering and tcpdump
When the vlan filtering is enabled on the bridge, but the filter is not configured on the bridge device itself, running tcpdump on the bridge device will result in a an Oops with NULL pointer dereference. The reason is that br_pass_frame_up() will bypass the vlan check because promisc flag is set. It will then try to get the table pointer and process the packet based on the table. Since the table pointer is NULL, we oops. Catch this special condition in br_handle_vlan(). Reported-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp> CC: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> Acked-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 53d6471 commit fc92f74

File tree

2 files changed

+20
-5
lines changed

2 files changed

+20
-5
lines changed

net/bridge/br_input.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ static int br_pass_frame_up(struct sk_buff *skb)
2929
struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
3030
struct net_bridge *br = netdev_priv(brdev);
3131
struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats);
32+
struct net_port_vlans *pv;
3233

3334
u64_stats_update_begin(&brstats->syncp);
3435
brstats->rx_packets++;
@@ -39,18 +40,18 @@ static int br_pass_frame_up(struct sk_buff *skb)
3940
* packet is allowed except in promisc modue when someone
4041
* may be running packet capture.
4142
*/
43+
pv = br_get_vlan_info(br);
4244
if (!(brdev->flags & IFF_PROMISC) &&
43-
!br_allowed_egress(br, br_get_vlan_info(br), skb)) {
45+
!br_allowed_egress(br, pv, skb)) {
4446
kfree_skb(skb);
4547
return NET_RX_DROP;
4648
}
4749

48-
skb = br_handle_vlan(br, br_get_vlan_info(br), skb);
49-
if (!skb)
50-
return NET_RX_DROP;
51-
5250
indev = skb->dev;
5351
skb->dev = brdev;
52+
skb = br_handle_vlan(br, pv, skb);
53+
if (!skb)
54+
return NET_RX_DROP;
5455

5556
return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
5657
netif_receive_skb);

net/bridge/br_vlan.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,20 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
128128
if (!br->vlan_enabled)
129129
goto out;
130130

131+
/* Vlan filter table must be configured at this point. The
132+
* only exception is the bridge is set in promisc mode and the
133+
* packet is destined for the bridge device. In this case
134+
* pass the packet as is.
135+
*/
136+
if (!pv) {
137+
if ((br->dev->flags & IFF_PROMISC) && skb->dev == br->dev) {
138+
goto out;
139+
} else {
140+
kfree_skb(skb);
141+
return NULL;
142+
}
143+
}
144+
131145
/* At this point, we know that the frame was filtered and contains
132146
* a valid vlan id. If the vlan id is set in the untagged bitmap,
133147
* send untagged; otherwise, send tagged.

0 commit comments

Comments
 (0)