diff options
author | Eric Dumazet <edumazet@google.com> | 2013-05-24 05:49:58 +0000 |
---|---|---|
committer | Willy Tarreau <w@1wt.eu> | 2014-05-19 07:53:42 +0200 |
commit | 09ef3754dffadf39076a402bc1ca7883c3fa2b73 (patch) | |
tree | f3f7b8ec5c4213aeea8687d3535bce328d028788 | |
parent | 46e280b6b2d0b0849c902289579e756ead08a6d8 (diff) | |
download | powerkvm-09ef3754dffadf39076a402bc1ca7883c3fa2b73.tar.gz |
ip_tunnel: fix kernel panic with icmp_dest_unreach
[ Upstream commit a622260254ee481747cceaaa8609985b29a31565 ]
Daniel Petre reported crashes in icmp_dst_unreach() with following call
graph:
Daniel found a similar problem mentioned in
http://lkml.indiana.edu/hypermail/linux/kernel/1007.0/00961.html
And indeed this is the root cause : skb->cb[] contains data fooling IP
stack.
We must clear IPCB in ip_tunnel_xmit() sooner in case dst_link_failure()
is called. Or else skb->cb[] might contain garbage from GSO segmentation
layer.
A similar fix was tested on linux-3.9, but gre code was refactored in
linux-3.10. I'll send patches for stable kernels as well.
Many thanks to Daniel for providing reports, patches and testing !
Reported-by: Daniel Petre <daniel.petre@rcs-rds.ro>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Willy Tarreau <w@1wt.eu>
-rw-r--r-- | net/ipv4/ipip.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 860b5c5d88a251..49aa1ad4f74c28 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -408,6 +408,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if (tos&1) tos = old_iph->tos; + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); if (!dst) { /* NBMA tunnel */ if ((rt = skb_rtable(skb)) == NULL) { @@ -494,7 +495,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) skb->transport_header = skb->network_header; skb_push(skb, sizeof(struct iphdr)); skb_reset_network_header(skb); - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED); skb_dst_drop(skb); |