geneve: avoid use-after-free of skb->data
authorSabrina Dubroca <sd@queasysnail.net>
Fri, 2 Dec 2016 15:49:29 +0000 (16:49 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 10 Dec 2016 18:07:24 +0000 (19:07 +0100)
[ Upstream commit 5b01014759991887b1e450c9def01e58c02ab81b ]

geneve{,6}_build_skb can end up doing a pskb_expand_head(), which
makes the ip_hdr(skb) reference we stashed earlier stale. Since it's
only needed as an argument to ip_tunnel_ecn_encap(), move this
directly in the function call.

Fixes: 08399efc6319 ("geneve: ensure ECN info is handled properly in all tx/rx paths")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Reviewed-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/geneve.c

index 4827c6987ac3f87234e7b8acb64bb9d6bbd03c94..f0961cbaf87ed610371db39d24b40da0d2488888 100644 (file)
@@ -815,7 +815,6 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        struct geneve_dev *geneve = netdev_priv(dev);
        struct geneve_sock *gs4 = geneve->sock4;
        struct rtable *rt = NULL;
-       const struct iphdr *iip; /* interior IP header */
        int err = -EINVAL;
        struct flowi4 fl4;
        __u8 tos, ttl;
@@ -842,8 +841,6 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
        skb_reset_mac_header(skb);
 
-       iip = ip_hdr(skb);
-
        if (info) {
                const struct ip_tunnel_key *key = &info->key;
                u8 *opts = NULL;
@@ -859,7 +856,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                if (unlikely(err))
                        goto err;
 
-               tos = ip_tunnel_ecn_encap(key->tos, iip, skb);
+               tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
                ttl = key->ttl;
                df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
        } else {
@@ -869,7 +866,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                if (unlikely(err))
                        goto err;
 
-               tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, iip, skb);
+               tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb);
                ttl = geneve->ttl;
                if (!ttl && IN_MULTICAST(ntohl(fl4.daddr)))
                        ttl = 1;
@@ -903,7 +900,6 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        struct geneve_dev *geneve = netdev_priv(dev);
        struct geneve_sock *gs6 = geneve->sock6;
        struct dst_entry *dst = NULL;
-       const struct iphdr *iip; /* interior IP header */
        int err = -EINVAL;
        struct flowi6 fl6;
        __u8 prio, ttl;
@@ -927,8 +923,6 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
        skb_reset_mac_header(skb);
 
-       iip = ip_hdr(skb);
-
        if (info) {
                const struct ip_tunnel_key *key = &info->key;
                u8 *opts = NULL;
@@ -945,7 +939,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                if (unlikely(err))
                        goto err;
 
-               prio = ip_tunnel_ecn_encap(key->tos, iip, skb);
+               prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
                ttl = key->ttl;
        } else {
                udp_csum = false;
@@ -954,7 +948,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                if (unlikely(err))
                        goto err;
 
-               prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, iip, skb);
+               prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, ip_hdr(skb), skb);
                ttl = geneve->ttl;
                if (!ttl && ipv6_addr_is_multicast(&fl6.daddr))
                        ttl = 1;