net: bridge: don't cache ether dest pointer on input
authorNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Tue, 2 Jul 2019 12:00:20 +0000 (15:00 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 2 Jul 2019 18:53:03 +0000 (11:53 -0700)
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>
net/bridge/br_input.c

index 21b74e7..52c7129 100644 (file)
@@ -74,7 +74,6 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
        struct net_bridge_fdb_entry *dst = NULL;
        struct net_bridge_mdb_entry *mdst;
        bool local_rcv, mcast_hit = false;
-       const unsigned char *dest;
        struct net_bridge *br;
        u16 vid = 0;
 
@@ -92,10 +91,9 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
                br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false);
 
        local_rcv = !!(br->dev->flags & IFF_PROMISC);
-       dest = eth_hdr(skb)->h_dest;
-       if (is_multicast_ether_addr(dest)) {
+       if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
                /* by definition the broadcast is also a multicast address */
-               if (is_broadcast_ether_addr(dest)) {
+               if (is_broadcast_ether_addr(eth_hdr(skb)->h_dest)) {
                        pkt_type = BR_PKT_BROADCAST;
                        local_rcv = true;
                } else {
@@ -145,7 +143,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
                }
                break;
        case BR_PKT_UNICAST:
-               dst = br_fdb_find_rcu(br, dest, vid);
+               dst = br_fdb_find_rcu(br, eth_hdr(skb)->h_dest, vid);
        default:
                break;
        }