diff mbox series

[net] ipv6: sit: fix skb_under_panic with overflowed needed_headroom

Message ID 20250325095449.2594874-1-wangliang74@huawei.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [net] ipv6: sit: fix skb_under_panic with overflowed needed_headroom | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag present in non-next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit fail Errors and warnings before: 7 this patch: 7
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers success CCed 8 of 8 maintainers
netdev/build_clang fail Errors and warnings before: 8 this patch: 8
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success Fixes tag looks correct
netdev/build_allmodconfig_warn fail Errors and warnings before: 7 this patch: 7
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 30 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Wang Liang March 25, 2025, 9:54 a.m. UTC
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@syzkaller.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@huawei.com>
---
 net/ipv6/sit.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

Comments

Jakub Kicinski March 26, 2025, 11:47 a.m. UTC | #1
On Tue, 25 Mar 2025 17:54:49 +0800 Wang Liang wrote:
> 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.

Sorry for the inconvenience but could you repost this patch?
Our CI was broken when you posted and we currently don't have
a way to re-trigger it :(
Wang Liang March 27, 2025, 1:19 a.m. UTC | #2
在 2025/3/26 19:47, Jakub Kicinski 写道:
> On Tue, 25 Mar 2025 17:54:49 +0800 Wang Liang wrote:
>> 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.
> Sorry for the inconvenience but could you repost this patch?
> Our CI was broken when you posted and we currently don't have
> a way to re-trigger it :(


Ok, I will send this patch again.
diff mbox series

Patch

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)