]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
udp: fix potential use-after-free in tunnel segmentation
authorXuanqiang Luo <luoxuanqiang@kylinos.cn>
Thu, 30 Jul 2026 09:35:54 +0000 (17:35 +0800)
committerJakub Kicinski <kuba@kernel.org>
Tue, 4 Aug 2026 01:32:47 +0000 (18:32 -0700)
__skb_udp_tunnel_segment() gets the UDP header before ensuring the
tunnel header is in the skb head. If the pull reallocates skb->head,
the saved UDP header pointer is no longer valid.

Get the UDP header after the pull to avoid a potential use-after-free.

Fixes: dbef491ebe7f ("udp: Use uh->len instead of skb->len to compute checksum in segmentation")
Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Reviewed-by: Antoine Tenart <atenart@kernel.org>
Link: https://patch.msgid.link/20260730093554.68127-1-xuanqiang.luo@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv4/udp_offload.c

index 29651b1a0bc704f46aafb67bc42f81ec3defca40..abcd3cc2d9a385e7f92fdff02aa0cb59c93e453c 100644 (file)
@@ -178,17 +178,19 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
        int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
        bool remcsum, need_csum, offload_csum, gso_partial;
        struct sk_buff *segs = ERR_PTR(-EINVAL);
-       struct udphdr *uh = udp_hdr(skb);
        u16 mac_offset = skb->mac_header;
        __be16 protocol = skb->protocol;
        u16 mac_len = skb->mac_len;
        int udp_offset, outer_hlen;
+       struct udphdr *uh;
        __wsum partial;
        bool need_ipsec;
 
        if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
                goto out;
 
+       uh = udp_hdr(skb);
+
        /* Adjust partial header checksum to negate old length.
         * We cannot rely on the value contained in uh->len as it is
         * possible that the actual value exceeds the boundaries of the