ip_tunnel: be careful when accessing the inner header
authorPaolo Abeni <pabeni@redhat.com>
Mon, 24 Sep 2018 13:48:19 +0000 (15:48 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 24 Sep 2018 19:27:04 +0000 (12:27 -0700)
Cong noted that we need the same checks introduced by commit 76c0ddd8c3a6
("ip6_tunnel: be careful when accessing the inner header")
even for ipv4 tunnels.

Fixes: c54419321455 ("GRE: Refactor GRE tunneling code.")
Suggested-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/ip_tunnel.c

index c4f5602308edca064297fe8764764f65ebe84569..284a22154b4e6cb129ca7dfd127ce11e306dba19 100644 (file)
@@ -627,6 +627,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
                    const struct iphdr *tnl_params, u8 protocol)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
+       unsigned int inner_nhdr_len = 0;
        const struct iphdr *inner_iph;
        struct flowi4 fl4;
        u8     tos, ttl;
@@ -636,6 +637,14 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        __be32 dst;
        bool connected;
 
+       /* ensure we can access the inner net header, for several users below */
+       if (skb->protocol == htons(ETH_P_IP))
+               inner_nhdr_len = sizeof(struct iphdr);
+       else if (skb->protocol == htons(ETH_P_IPV6))
+               inner_nhdr_len = sizeof(struct ipv6hdr);
+       if (unlikely(!pskb_may_pull(skb, inner_nhdr_len)))
+               goto tx_error;
+
        inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
        connected = (tunnel->parms.iph.daddr != 0);