[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1032642: iproute2: ip tunnel change ip6gre to gre crashes with stack smash



On Sat, 25 Mar 2023 at 00:39, Bernhard Übelacker <bernhardu@mailbox.org> wrote:
>
> Dear Maintainer,
> I tried to find out where exactly the stack smashing takes place.
> And found the ioctl SIOCCHGTUNNEL did write more than the 52 bytes
> allocated in variable old_p, by that overwriting the stack canary.
>
> Kind regards,
> Bernhard
>
>
> (gdb)
> 0x000055555557589f      62      {
> 1: x/i $pc
> => 0x55555557589f <parse_args+31>:      mov    %fs:0x28,%rax
> (gdb)
> 0x00005555555758a8      62      {
> 1: x/i $pc
> => 0x5555555758a8 <parse_args+40>:      mov    %rax,0x68(%rsp)
> (gdb) print/x $rax
> $1 = 0xbf9b77d893accd00
> (gdb) print/x $rsp + 0x68
> $2 = 0x7fffffffea28
>
>
> (gdb)
> 0x00007ffff7e575f5      120     in ../sysdeps/unix/syscall-template.S
> 1: x/i $pc
> => 0x7ffff7e575f5 <ioctl+5>:    syscall
> 2: /x *(uint64_t*)0x7fffffffea28 = 0xbf9b77d893accd00
> (gdb) bt
> #0  0x00007ffff7e575f5 in ioctl () at ../sysdeps/unix/syscall-template.S:120
> #1  0x0000555555578230 in tnl_get_ioctl (basedev=0x7fffffffee8f "gre1", p=<optimized out>) at tunnel.c:77
> #2  0x0000555555576243 in parse_args (argc=9, argv=0x7fffffffec50, cmd=35315, p=0x7fffffffea70) at iptunnel.c:181
> #3  0x00005555555762fb in do_add (cmd=35315, argc=<optimized out>, argv=<optimized out>) at iptunnel.c:260
> #4  0x000055555556258b in do_cmd (argv0=0x7fffffffee81 "tunnel", argc=11, argv=0x7fffffffec40) at ip.c:133
> #5  0x0000555555561fc2 in main (argc=12, argv=0x7fffffffec38) at ip.c:344
> (gdb) stepi
> 0x00007ffff7e575f7      120     in ../sysdeps/unix/syscall-template.S
> 1: x/i $pc
> => 0x7ffff7e575f7 <ioctl+7>:    cmp    $0xfffffffffffff001,%rax
> 2: /x *(uint64_t*)0x7fffffffea28 = 0x200000000000000
>
> (gdb) print &old_p
> $7 = (struct ip_tunnel_parm *) 0x7fffffffe9f0
> (gdb) print sizeof(old_p)
> $8 = 52
> (gdb) print/x 0x7fffffffe9f0 + 52
> $9 = 0x7fffffffea24
>
> (gdb) list iptunnel.c:181
> 178                             if (cmd == SIOCCHGTUNNEL && count == 0) {
> 179                                     struct ip_tunnel_parm old_p = {};
> 180
> 181                                     if (tnl_get_ioctl(*argv, &old_p))
> 182                                             return -1;

Hi David and Stephen,

To reproduce, build iproute2 with -fstack-protector-strong in CFLAGS, and run:

ip tunnel add gre1 mode ip6gre local 2001:db8::1 remote 2001:db8::2 ttl 255
ip tunnel change gre1 mode gre local 192.168.0.0 remote 192.168.0.1 ttl 255

You'll get:

*** stack smashing detected ***: terminated
Aborted

This happens because iproute2 just assumes the tunnel is ipv4, but the
kernel "knows" it's actually ip6gre so when calling the SIOCGETTUNNEL
ioctl it writes back a struct ip6_tnl_parm2 into the struct
ip_tunnel_parm which is smaller, so the stack gets overwritten. Is
there any way to tell from userspace whether a gre is v4 or v6 before
doing an ioctl? The ioctls don't take/return a size parameter as far
as I can see...


Reply to: