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>
This commit is contained in:
Eric Dumazet 2012-12-20 16:00:27 +00:00 коммит произвёл David S. Miller
Родитель 412ed94744
Коммит f7e75ba177
1 изменённых файлов: 5 добавлений и 1 удалений

Просмотреть файл

@ -750,6 +750,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
int gre_hlen; int gre_hlen;
__be32 dst; __be32 dst;
int mtu; int mtu;
u8 ttl;
if (skb->ip_summed == CHECKSUM_PARTIAL && if (skb->ip_summed == CHECKSUM_PARTIAL &&
skb_checksum_help(skb)) 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; goto tx_error;
} }
ttl = tiph->ttl;
tos = tiph->tos; tos = tiph->tos;
if (tos == 1) { if (tos == 1) {
tos = 0; 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); dev_kfree_skb(skb);
skb = new_skb; skb = new_skb;
old_iph = ip_hdr(skb); old_iph = ip_hdr(skb);
/* Warning : tiph value might point to freed memory */
} }
skb_reset_transport_header(skb); 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->tos = ipgre_ecn_encapsulate(tos, old_iph, skb);
iph->daddr = fl4.daddr; iph->daddr = fl4.daddr;
iph->saddr = fl4.saddr; iph->saddr = fl4.saddr;
iph->ttl = ttl;
if ((iph->ttl = tiph->ttl) == 0) { if (ttl == 0) {
if (skb->protocol == htons(ETH_P_IP)) if (skb->protocol == htons(ETH_P_IP))
iph->ttl = old_iph->ttl; iph->ttl = old_iph->ttl;
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)