[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250325095449.2594874-1-wangliang74@huawei.com>
Date: Tue, 25 Mar 2025 17:54:49 +0800
From: Wang Liang <wangliang74@...wei.com>
To: <davem@...emloft.net>, <dsahern@...nel.org>, <edumazet@...gle.com>,
<kuba@...nel.org>, <pabeni@...hat.com>, <horms@...nel.org>,
<cong.wang@...edance.com>, <kuniyu@...zon.com>
CC: <yuehaibing@...wei.com>, <zhangchangzhong@...wei.com>,
<wangliang74@...wei.com>, <netdev@...r.kernel.org>,
<linux-kernel@...r.kernel.org>
Subject: [PATCH net] ipv6: sit: fix skb_under_panic with overflowed needed_headroom
When create ipip6 tunnel, if tunnel->parms.link is assigned to the previous
created tunnel device, the dev->needed_headroom will increase based on the
previous one.
If the number of tunnel device is sufficient, the needed_headroom can be
overflowed. The overflow happens like this:
ipip6_newlink
ipip6_tunnel_create
register_netdevice
ipip6_tunnel_init
ipip6_tunnel_bind_dev
t_hlen = tunnel->hlen + sizeof(struct iphdr); // 40
hlen = tdev->hard_header_len + tdev->needed_headroom; // 65496
dev->needed_headroom = t_hlen + hlen; // 65536 -> 0
The value of LL_RESERVED_SPACE(rt->dst.dev) may be HH_DATA_MOD, that leads
to a small skb allocated in __ip_append_data(), which triggers a
skb_under_panic:
------------[ cut here ]------------
kernel BUG at net/core/skbuff.c:209!
Oops: invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI
CPU: 0 UID: 0 PID: 24133 Comm: test Tainted: G W 6.14.0-rc7-00067-g76b6905c11fd-dirty #1
Tainted: [W]=WARN
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014
RIP: 0010:skb_panic+0x156/0x1d0
Call Trace:
<TASK>
skb_push+0xc8/0xe0
fou_build_udp+0x31/0x3a0
gue_build_header+0xf7/0x150
ip_tunnel_xmit+0x684/0x3660
sit_tunnel_xmit__.isra.0+0xeb/0x150
sit_tunnel_xmit+0x2e3/0x2930
dev_hard_start_xmit+0x1a6/0x7b0
__dev_queue_xmit+0x2fa9/0x4120
neigh_connected_output+0x39e/0x590
ip_finish_output2+0x7bb/0x1f00
__ip_finish_output+0x442/0x940
ip_finish_output+0x31/0x380
ip_mc_output+0x1c4/0x6a0
ip_send_skb+0x339/0x570
udp_send_skb+0x905/0x1540
udp_sendmsg+0x17c8/0x28f0
udpv6_sendmsg+0x17f1/0x2c30
inet6_sendmsg+0x105/0x140
____sys_sendmsg+0x801/0xc70
___sys_sendmsg+0x110/0x1b0
__sys_sendmmsg+0x1f2/0x410
__x64_sys_sendmmsg+0x99/0x100
do_syscall_64+0x6e/0x1c0
entry_SYSCALL_64_after_hwframe+0x76/0x7e
---[ end trace 0000000000000000 ]---
Fix this by add check for needed_headroom in ipip6_tunnel_bind_dev().
Reported-by: syzbot+4c63f36709a642f801c5@...kaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=4c63f36709a642f801c5
Fixes: c88f8d5cd95f ("sit: update dev->needed_headroom in ipip6_tunnel_bind_dev()")
Signed-off-by: Wang Liang <wangliang74@...wei.com>
---
net/ipv6/sit.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 39bd8951bfca..1662b735c5e3 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -1095,7 +1095,7 @@ static netdev_tx_t sit_tunnel_xmit(struct sk_buff *skb,
}
-static void ipip6_tunnel_bind_dev(struct net_device *dev)
+static int ipip6_tunnel_bind_dev(struct net_device *dev)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
int t_hlen = tunnel->hlen + sizeof(struct iphdr);
@@ -1134,7 +1134,12 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
WRITE_ONCE(dev->mtu, mtu);
hlen = tdev->hard_header_len + tdev->needed_headroom;
}
+
+ if (t_hlen + hlen > U16_MAX)
+ return -EOVERFLOW;
+
dev->needed_headroom = t_hlen + hlen;
+ return 0;
}
static void ipip6_tunnel_update(struct ip_tunnel *t,
@@ -1452,7 +1457,9 @@ static int ipip6_tunnel_init(struct net_device *dev)
tunnel->net = dev_net(dev);
strcpy(tunnel->parms.name, dev->name);
- ipip6_tunnel_bind_dev(dev);
+ err = ipip6_tunnel_bind_dev(dev);
+ if (err)
+ return err;
err = dst_cache_init(&tunnel->dst_cache, GFP_KERNEL);
if (err)
--
2.34.1
Powered by blists - more mailing lists