]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
vxlan: use pskb_network_may_pull() in route_shortcircuit()
authorEric Dumazet <edumazet@google.com>
Thu, 23 Jul 2026 14:42:48 +0000 (14:42 +0000)
committerJakub Kicinski <kuba@kernel.org>
Mon, 27 Jul 2026 22:15:13 +0000 (15:15 -0700)
route_shortcircuit() currently calls pskb_may_pull(skb, sizeof(struct iphdr))
(or ipv6hdr), which checks if bytes are available starting from skb->data.

However, in vxlan_xmit(), skb->data points to the MAC header, so
skb_network_offset(skb) is ETH_HLEN (14 bytes). Using pskb_may_pull(skb, 20)
only checks 20 bytes from skb->data (which is 14 bytes MAC header + 6 bytes of
IP header), leaving the rest of the IP header potentially un-pulled in non-linear
frags. Subsequent dereferences of ip_hdr(skb)->daddr can read beyond the pulled
linear buffer length.

Fix this by using pskb_network_may_pull(), which adds skb_network_offset(skb) to
the length check to ensure the full network header is present in the linear buffer.

Fixes: e4f67addf158 ("add DOVE extensions for VXLAN")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20260723144249.759100-5-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/vxlan/vxlan_core.c

index be3c2bc2cd9accec8d37194141fa31f60392c039..2163e2687db029e19fefdf279095209e94b18a41 100644 (file)
@@ -2111,7 +2111,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
        {
                struct iphdr *pip;
 
-               if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+               if (!pskb_network_may_pull(skb, sizeof(struct iphdr)))
                        return false;
                pip = ip_hdr(skb);
                n = neigh_lookup(&arp_tbl, &pip->daddr, dev);
@@ -2137,7 +2137,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
                 */
                if (!ipv6_mod_enabled())
                        return false;
-               if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+               if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr)))
                        return false;
                pip6 = ipv6_hdr(skb);
                n = neigh_lookup(&nd_tbl, &pip6->daddr, dev);