ip6_tunnel: fix possible use-after-free on xmit [Linux 4.9.189]

This Linux kernel change "ip6_tunnel: fix possible use-after-free on xmit" is included in the Linux 4.9.189 release. This change is authored by Haishuang Yan <yanhaishuang [at] cmss.chinamobile.com> on Fri Jul 26 00:40:17 2019 +0800. The commit for this change in Linux stable tree is dfb9883 (patch) which is from upstream commit 01f5bff. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 01f5bff.

ip6_tunnel: fix possible use-after-free on xmit

[ Upstream commit 01f5bffad555f8e22a61f4b1261fe09cf1b96994 ]

ip4ip6/ip6ip6 tunnels run iptunnel_handle_offloads on xmit which
can cause a possible use-after-free accessing iph/ipv6h pointer
since the packet will be 'uncloned' running pskb_expand_head if
it is a cloned gso skb.

Fixes: 0e9a709560db ("ip6_tunnel, ip6_gre: fix setting of DSCP on encapsulated packets")
Signed-off-by: Haishuang Yan <yanhaishuang@cmss.chinamobile.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

There are 8 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 net/ipv6/ip6_tunnel.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 42f3636..cc28b86 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1275,11 +1275,11 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
            fl6.flowi6_mark = skb->mark;
    }

+   dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
+
    if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
        return -1;

-   dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
-
    skb_set_inner_ipproto(skb, IPPROTO_IPIP);

    err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
@@ -1362,11 +1362,11 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
            fl6.flowi6_mark = skb->mark;
    }

+   dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
+
    if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
        return -1;

-   dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
-
    skb_set_inner_ipproto(skb, IPPROTO_IPV6);

    err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,

Leave a Reply

Your email address will not be published. Required fields are marked *