diff options
author | Nikolay Aleksandrov <nikolay@cumulusnetworks.com> | 2019-07-02 08:00:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-07-02 14:53:03 -0400 |
commit | 3d26eb8ad1e9b906433903ce05f775cf038e747f (patch) | |
tree | f3b35856d12d170744c54dd5a056b23a74218043 | |
parent | 3b26a5d03d35d8f732d75951218983c0f7f68dff (diff) |
net: bridge: don't cache ether dest pointer on input
We would cache ether dst pointer on input in br_handle_frame_finish but
after the neigh suppress code that could lead to a stale pointer since
both ipv4 and ipv6 suppress code do pskb_may_pull. This means we have to
always reload it after the suppress code so there's no point in having
it cached just retrieve it directly.
Fixes: 057658cb33fbf ("bridge: suppress arp pkts on BR_NEIGH_SUPPRESS ports")
Fixes: ed842faeb2bd ("bridge: suppress nd pkts on BR_NEIGH_SUPPRESS ports")
Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/bridge/br_input.c | 8 |
1 files changed, 3 insertions, 5 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 21b74e7a7b2f..52c712984cc7 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -74,7 +74,6 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb | |||
74 | struct net_bridge_fdb_entry *dst = NULL; | 74 | struct net_bridge_fdb_entry *dst = NULL; |
75 | struct net_bridge_mdb_entry *mdst; | 75 | struct net_bridge_mdb_entry *mdst; |
76 | bool local_rcv, mcast_hit = false; | 76 | bool local_rcv, mcast_hit = false; |
77 | const unsigned char *dest; | ||
78 | struct net_bridge *br; | 77 | struct net_bridge *br; |
79 | u16 vid = 0; | 78 | u16 vid = 0; |
80 | 79 | ||
@@ -92,10 +91,9 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb | |||
92 | br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false); | 91 | br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false); |
93 | 92 | ||
94 | local_rcv = !!(br->dev->flags & IFF_PROMISC); | 93 | local_rcv = !!(br->dev->flags & IFF_PROMISC); |
95 | dest = eth_hdr(skb)->h_dest; | 94 | if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) { |
96 | if (is_multicast_ether_addr(dest)) { | ||
97 | /* by definition the broadcast is also a multicast address */ | 95 | /* by definition the broadcast is also a multicast address */ |
98 | if (is_broadcast_ether_addr(dest)) { | 96 | if (is_broadcast_ether_addr(eth_hdr(skb)->h_dest)) { |
99 | pkt_type = BR_PKT_BROADCAST; | 97 | pkt_type = BR_PKT_BROADCAST; |
100 | local_rcv = true; | 98 | local_rcv = true; |
101 | } else { | 99 | } else { |
@@ -145,7 +143,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb | |||
145 | } | 143 | } |
146 | break; | 144 | break; |
147 | case BR_PKT_UNICAST: | 145 | case BR_PKT_UNICAST: |
148 | dst = br_fdb_find_rcu(br, dest, vid); | 146 | dst = br_fdb_find_rcu(br, eth_hdr(skb)->h_dest, vid); |
149 | default: | 147 | default: |
150 | break; | 148 | break; |
151 | } | 149 | } |