diff options
author | Eric Dumazet <edumazet@google.com> | 2012-12-20 11:00:27 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-12-21 16:14:01 -0500 |
commit | f7e75ba1772bc712af0070655ffd8b09906993b5 (patch) | |
tree | ef32b318efe584f845f05eb7f65daca803abb6a1 /net/ipv4/ip_gre.c | |
parent | 412ed94744d16806fbec3bd250fd94e71cde5a1f (diff) |
ip_gre: fix possible use after free
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>
Diffstat (limited to 'net/ipv4/ip_gre.c')
-rw-r--r-- | net/ipv4/ip_gre.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 8fcf0ed76548..58cb627560dd 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -750,6 +750,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
750 | int gre_hlen; | 750 | int gre_hlen; |
751 | __be32 dst; | 751 | __be32 dst; |
752 | int mtu; | 752 | int mtu; |
753 | u8 ttl; | ||
753 | 754 | ||
754 | if (skb->ip_summed == CHECKSUM_PARTIAL && | 755 | if (skb->ip_summed == CHECKSUM_PARTIAL && |
755 | skb_checksum_help(skb)) | 756 | skb_checksum_help(skb)) |
@@ -815,6 +816,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
815 | goto tx_error; | 816 | goto tx_error; |
816 | } | 817 | } |
817 | 818 | ||
819 | ttl = tiph->ttl; | ||
818 | tos = tiph->tos; | 820 | tos = tiph->tos; |
819 | if (tos == 1) { | 821 | if (tos == 1) { |
820 | tos = 0; | 822 | tos = 0; |
@@ -907,6 +909,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
907 | dev_kfree_skb(skb); | 909 | dev_kfree_skb(skb); |
908 | skb = new_skb; | 910 | skb = new_skb; |
909 | old_iph = ip_hdr(skb); | 911 | old_iph = ip_hdr(skb); |
912 | /* Warning : tiph value might point to freed memory */ | ||
910 | } | 913 | } |
911 | 914 | ||
912 | skb_reset_transport_header(skb); | 915 | skb_reset_transport_header(skb); |
@@ -930,8 +933,9 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
930 | iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb); | 933 | iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb); |
931 | iph->daddr = fl4.daddr; | 934 | iph->daddr = fl4.daddr; |
932 | iph->saddr = fl4.saddr; | 935 | iph->saddr = fl4.saddr; |
936 | iph->ttl = ttl; | ||
933 | 937 | ||
934 | if ((iph->ttl = tiph->ttl) == 0) { | 938 | if (ttl == 0) { |
935 | if (skb->protocol == htons(ETH_P_IP)) | 939 | if (skb->protocol == htons(ETH_P_IP)) |
936 | iph->ttl = old_iph->ttl; | 940 | iph->ttl = old_iph->ttl; |
937 | #if IS_ENABLED(CONFIG_IPV6) | 941 | #if IS_ENABLED(CONFIG_IPV6) |