]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ip_gre: fix possible use after free
authorEric Dumazet <edumazet@google.com>
Thu, 20 Dec 2012 16:00:27 +0000 (16:00 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 21 Dec 2012 21:14:01 +0000 (13:14 -0800)
Once skb_realloc_headroom() is called, tiph might point to freed memory.

Cache tiph->ttl value before the reallocation, to avoid unexpected
behavior.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/ip_gre.c

index 8fcf0ed76548a31074293d26a671fbbd9a32845e..58cb627560dd21b30c8d08fb1909efd34234819b 100644 (file)
@@ -750,6 +750,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
        int    gre_hlen;
        __be32 dst;
        int    mtu;
+       u8     ttl;
 
        if (skb->ip_summed == CHECKSUM_PARTIAL &&
            skb_checksum_help(skb))
@@ -815,6 +816,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
                        goto tx_error;
        }
 
+       ttl = tiph->ttl;
        tos = tiph->tos;
        if (tos == 1) {
                tos = 0;
@@ -907,6 +909,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
                dev_kfree_skb(skb);
                skb = new_skb;
                old_iph = ip_hdr(skb);
+               /* Warning : tiph value might point to freed memory */
        }
 
        skb_reset_transport_header(skb);
@@ -930,8 +933,9 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
        iph->tos                =       ipgre_ecn_encapsulate(tos, old_iph, skb);
        iph->daddr              =       fl4.daddr;
        iph->saddr              =       fl4.saddr;
+       iph->ttl                =       ttl;
 
-       if ((iph->ttl = tiph->ttl) == 0) {
+       if (ttl == 0) {
                if (skb->protocol == htons(ETH_P_IP))
                        iph->ttl = old_iph->ttl;
 #if IS_ENABLED(CONFIG_IPV6)