Skip to content

Commit 85f46c6

Browse files
Vlad Yasevichdavem330
authored andcommitted
bridge: Verify that a vlan is allowed to egress on given port
When bridge forwards a frame, make sure that a frame is allowed to egress on that port. Signed-off-by: Vlad Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent a37b85c commit 85f46c6

File tree

4 files changed

+41
-0
lines changed

4 files changed

+41
-0
lines changed

net/bridge/br_forward.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ static inline int should_deliver(const struct net_bridge_port *p,
3131
const struct sk_buff *skb)
3232
{
3333
return (((p->flags & BR_HAIRPIN_MODE) || skb->dev != p->dev) &&
34+
br_allowed_egress(p->br, nbp_get_vlan_info(p), skb) &&
3435
p->state == BR_STATE_FORWARDING);
3536
}
3637

net/bridge/br_input.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ static int br_pass_frame_up(struct sk_buff *skb)
3535
brstats->rx_bytes += skb->len;
3636
u64_stats_update_end(&brstats->syncp);
3737

38+
/* Bridge is just like any other port. Make sure the
39+
* packet is allowed except in promisc modue when someone
40+
* may be running packet capture.
41+
*/
42+
if (!(brdev->flags & IFF_PROMISC) &&
43+
!br_allowed_egress(br, br_get_vlan_info(br), skb)) {
44+
kfree_skb(skb);
45+
return NET_RX_DROP;
46+
}
47+
3848
indev = skb->dev;
3949
skb->dev = brdev;
4050

net/bridge/br_private.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,9 @@ static inline void br_mdb_uninit(void)
554554
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
555555
extern bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
556556
struct sk_buff *skb);
557+
extern bool br_allowed_egress(struct net_bridge *br,
558+
const struct net_port_vlans *v,
559+
const struct sk_buff *skb);
557560
extern int br_vlan_add(struct net_bridge *br, u16 vid);
558561
extern int br_vlan_delete(struct net_bridge *br, u16 vid);
559562
extern void br_vlan_flush(struct net_bridge *br);
@@ -598,6 +601,13 @@ static inline bool br_allowed_ingress(struct net_bridge *br,
598601
return true;
599602
}
600603

604+
static inline bool br_allowed_egress(struct net_bridge *br,
605+
const struct net_port_vlans *v,
606+
const struct sk_buff *skb)
607+
{
608+
return true;
609+
}
610+
601611
static inline int br_vlan_add(struct net_bridge *br, u16 vid)
602612
{
603613
return -EOPNOTSUPP;

net/bridge/br_vlan.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,26 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
8989
return false;
9090
}
9191

92+
/* Called under RCU. */
93+
bool br_allowed_egress(struct net_bridge *br,
94+
const struct net_port_vlans *v,
95+
const struct sk_buff *skb)
96+
{
97+
u16 vid;
98+
99+
if (!br->vlan_enabled)
100+
return true;
101+
102+
if (!v)
103+
return false;
104+
105+
br_vlan_get_tag(skb, &vid);
106+
if (test_bit(vid, v->vlan_bitmap))
107+
return true;
108+
109+
return false;
110+
}
111+
92112
/* Must be protected by RTNL */
93113
int br_vlan_add(struct net_bridge *br, u16 vid)
94114
{

0 commit comments

Comments
 (0)