lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CANn89iJn5gARyEPHeYxZxERpERdNKMngMcP1BbKrW9ebxB-tRw@mail.gmail.com>
Date: Thu, 27 Mar 2025 05:32:04 +0100
From: Eric Dumazet <edumazet@...gle.com>
To: Wang Liang <wangliang74@...wei.com>
Cc: davem@...emloft.net, dsahern@...nel.org, kuba@...nel.org, 
	pabeni@...hat.com, horms@...nel.org, kuniyu@...zon.com, yuehaibing@...wei.com, 
	zhangchangzhong@...wei.com, netdev@...r.kernel.org, 
	linux-kernel@...r.kernel.org
Subject: Re: [PATCH net] ipv6: sit: fix skb_under_panic with overflowed needed_headroom

On Thu, Mar 27, 2025 at 2:48 AM Wang Liang <wangliang74@...wei.com> 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.
>
> If the number of tunnel device is sufficient, the needed_headroom can be
> overflowed. The overflow happens like this:

How many stacked devices would be needed to reach this point ?

I thought we had a limit, to make sure we do not overflow the kernel stack ?

>
>   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 ]---

Can you provide symbols ?

scripts/decode_stacktrace.sh is your friend.

>
> 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

Powered by Openwall GNU/*/Linux Powered by OpenVZ