| From 018fae30571975a5c4b132155c1749e03e709911 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 11 Dec 2025 17:35:50 +0000 |
| Subject: ip6_gre: make ip6gre_header() robust |
| |
| From: Eric Dumazet <edumazet@google.com> |
| |
| [ Upstream commit db5b4e39c4e63700c68a7e65fc4e1f1375273476 ] |
| |
| Over the years, syzbot found many ways to crash the kernel |
| in ip6gre_header() [1]. |
| |
| This involves team or bonding drivers ability to dynamically |
| change their dev->needed_headroom and/or dev->hard_header_len |
| |
| In this particular crash mld_newpack() allocated an skb |
| with a too small reserve/headroom, and by the time mld_sendpack() |
| was called, syzbot managed to attach an ip6gre device. |
| |
| [1] |
| skbuff: skb_under_panic: text:ffffffff8a1d69a8 len:136 put:40 head:ffff888059bc7000 data:ffff888059bc6fe8 tail:0x70 end:0x6c0 dev:team0 |
| ------------[ cut here ]------------ |
| kernel BUG at net/core/skbuff.c:213 ! |
| <TASK> |
| skb_under_panic net/core/skbuff.c:223 [inline] |
| skb_push+0xc3/0xe0 net/core/skbuff.c:2641 |
| ip6gre_header+0xc8/0x790 net/ipv6/ip6_gre.c:1371 |
| dev_hard_header include/linux/netdevice.h:3436 [inline] |
| neigh_connected_output+0x286/0x460 net/core/neighbour.c:1618 |
| neigh_output include/net/neighbour.h:556 [inline] |
| ip6_finish_output2+0xfb3/0x1480 net/ipv6/ip6_output.c:136 |
| __ip6_finish_output net/ipv6/ip6_output.c:-1 [inline] |
| ip6_finish_output+0x234/0x7d0 net/ipv6/ip6_output.c:220 |
| NF_HOOK_COND include/linux/netfilter.h:307 [inline] |
| ip6_output+0x340/0x550 net/ipv6/ip6_output.c:247 |
| NF_HOOK+0x9e/0x380 include/linux/netfilter.h:318 |
| mld_sendpack+0x8d4/0xe60 net/ipv6/mcast.c:1855 |
| mld_send_cr net/ipv6/mcast.c:2154 [inline] |
| mld_ifc_work+0x83e/0xd60 net/ipv6/mcast.c:2693 |
| |
| Fixes: c12b395a4664 ("gre: Support GRE over IPv6") |
| Reported-by: syzbot+43a2ebcf2a64b1102d64@syzkaller.appspotmail.com |
| Closes: https://lore.kernel.org/netdev/693b002c.a70a0220.33cd7b.0033.GAE@google.com/T/#u |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Link: https://patch.msgid.link/20251211173550.2032674-1-edumazet@google.com |
| Signed-off-by: Paolo Abeni <pabeni@redhat.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| net/ipv6/ip6_gre.c | 9 ++++++++- |
| 1 file changed, 8 insertions(+), 1 deletion(-) |
| |
| diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c |
| index c82a75510c0e..8bc3f05f594e 100644 |
| --- a/net/ipv6/ip6_gre.c |
| +++ b/net/ipv6/ip6_gre.c |
| @@ -1366,9 +1366,16 @@ static int ip6gre_header(struct sk_buff *skb, struct net_device *dev, |
| { |
| struct ip6_tnl *t = netdev_priv(dev); |
| struct ipv6hdr *ipv6h; |
| + int needed; |
| __be16 *p; |
| |
| - ipv6h = skb_push(skb, t->hlen + sizeof(*ipv6h)); |
| + needed = t->hlen + sizeof(*ipv6h); |
| + if (skb_headroom(skb) < needed && |
| + pskb_expand_head(skb, HH_DATA_ALIGN(needed - skb_headroom(skb)), |
| + 0, GFP_ATOMIC)) |
| + return -needed; |
| + |
| + ipv6h = skb_push(skb, needed); |
| ip6_flow_hdr(ipv6h, 0, ip6_make_flowlabel(dev_net(dev), skb, |
| t->fl.u.ip6.flowlabel, |
| true, &t->fl.u.ip6)); |
| -- |
| 2.51.0 |
| |