net/xfrm: stack-out-of-bounds in xfrm_state_find

From: Andrey Konovalov
Date: Thu Apr 20 2017 - 12:47:53 EST


Hi,

I've got the following error report while fuzzing the kernel with syzkaller.

On linux-next commit 4f7d029b9bf009fbee76bb10c0c4351a1870d2f3 (4.11-rc7).

A reproducer and .config are attached.

==================================================================
BUG: KASAN: stack-out-of-bounds in xfrm_state_find+0x2ce7/0x2f70 at
addr ffff88006654f790
Read of size 4 by task a.out/4065
page:ffffea00019953c0 count:0 mapcount:0 mapping: (null) index:0x0
flags: 0x100000000000000()
raw: 0100000000000000 0000000000000000 0000000000000000 00000000ffffffff
raw: 0000000000000000 ffffea00019953e0 0000000000000000 0000000000000000
page dumped because: kasan: bad access detected
CPU: 1 PID: 4065 Comm: a.out Not tainted 4.11.0-rc7+ #251
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:16
dump_stack+0x292/0x398 lib/dump_stack.c:52
kasan_report_error mm/kasan/report.c:212
kasan_report+0x4d8/0x510 mm/kasan/report.c:347
__asan_report_load4_noabort+0x14/0x20 mm/kasan/report.c:367
xfrm_state_find+0x2ce7/0x2f70 net/xfrm/xfrm_state.c:897
xfrm_tmpl_resolve_one net/xfrm/xfrm_policy.c:1470
xfrm_tmpl_resolve+0x308/0xc90 net/xfrm/xfrm_policy.c:1514
xfrm_resolve_and_create_bundle+0x16e/0x2590 net/xfrm/xfrm_policy.c:1889
xfrm_lookup+0xd72/0x1170 net/xfrm/xfrm_policy.c:2253
xfrm_lookup_route+0x39/0x1a0 net/xfrm/xfrm_policy.c:2375
ip_route_output_flow+0x7f/0xa0 net/ipv4/route.c:2483
udp_sendmsg+0x1565/0x2cd0 net/ipv4/udp.c:1015
udpv6_sendmsg+0x8af/0x3500 net/ipv6/udp.c:1083
inet_sendmsg+0x164/0x5b0 net/ipv4/af_inet.c:762
sock_sendmsg_nosec net/socket.c:633
sock_sendmsg+0xca/0x110 net/socket.c:643
SYSC_sendto+0x660/0x810 net/socket.c:1696
SyS_sendto+0x40/0x50 net/socket.c:1664
entry_SYSCALL_64_fastpath+0x1f/0xc2 arch/x86/entry/entry_64.S:204
RIP: 0033:0x7f3daefd0b79
RSP: 002b:00007ffdb39bb0b8 EFLAGS: 00000206 ORIG_RAX: 000000000000002c
RAX: ffffffffffffffda RBX: 00007ffdb39bb210 RCX: 00007f3daefd0b79
RDX: 0000000000000000 RSI: 0000000020001000 RDI: 0000000000000003
RBP: 00000000004004a0 R08: 0000000020013ff0 R09: 0000000000000010
R10: 0000000020000000 R11: 0000000000000206 R12: 0000000000000000
R13: 00007ffdb39bb210 R14: 0000000000000000 R15: 0000000000000000
Memory state around the buggy address:
ffff88006654f680: f1 f1 f1 00 f2 f2 f2 f2 f2 f2 f2 f8 f2 f2 f2 f2
ffff88006654f700: f2 f2 f2 00 00 00 00 f2 f2 f2 f2 00 00 00 00 00
>ffff88006654f780: 00 00 f2 f2 f2 f2 f2 00 00 00 00 00 00 00 00 00
^
ffff88006654f800: f2 f2 f2 f3 f3 f3 f3 00 00 00 00 00 00 00 00 00
ffff88006654f880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
==================================================================

Attachment: .config
Description: Binary data

// autogenerated by syzkaller (http://github.com/google/syzkaller)

#ifndef __NR_sendto
#define __NR_sendto 44
#endif
#ifndef __NR_mmap
#define __NR_mmap 9
#endif
#ifndef __NR_socket
#define __NR_socket 41
#endif
#ifndef __NR_setsockopt
#define __NR_setsockopt 54
#endif

#define _GNU_SOURCE

#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>

#include <linux/capability.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <linux/kvm.h>
#include <linux/sched.h>
#include <net/if_arp.h>

#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <pthread.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1,
uintptr_t a2, uintptr_t a3,
uintptr_t a4, uintptr_t a5,
uintptr_t a6, uintptr_t a7,
uintptr_t a8)
{
switch (nr) {
default:
return syscall(nr, a0, a1, a2, a3, a4, a5);
}
}

long r[91];
void main()
{
memset(r, -1, sizeof(r));
r[0] = execute_syscall(__NR_mmap, 0x20000000ul, 0x14000ul, 0x3ul,
0x32ul, 0xfffffffffffffffful, 0x0ul, 0, 0, 0);
r[1] = execute_syscall(__NR_socket, 0xaul, 0x2ul, 0x0ul, 0, 0, 0, 0,
0, 0);
(*(uint8_t*)0x20000f18 = (uint8_t)0x0);
(*(uint8_t*)0x20000f19 = (uint8_t)0x0);
(*(uint8_t*)0x20000f1a = (uint8_t)0x0);
(*(uint8_t*)0x20000f1b = (uint8_t)0x0);
(*(uint8_t*)0x20000f1c = (uint8_t)0x0);
(*(uint8_t*)0x20000f1d = (uint8_t)0x0);
(*(uint8_t*)0x20000f1e = (uint8_t)0x0);
(*(uint8_t*)0x20000f1f = (uint8_t)0x0);
(*(uint8_t*)0x20000f20 = (uint8_t)0x0);
(*(uint8_t*)0x20000f21 = (uint8_t)0x0);
(*(uint8_t*)0x20000f22 = (uint8_t)0x0);
(*(uint8_t*)0x20000f23 = (uint8_t)0x0);
(*(uint8_t*)0x20000f24 = (uint8_t)0x0);
(*(uint8_t*)0x20000f25 = (uint8_t)0x0);
(*(uint8_t*)0x20000f26 = (uint8_t)0x0);
(*(uint8_t*)0x20000f27 = (uint8_t)0x0);
(*(uint8_t*)0x20000f28 = (uint8_t)0xfd);
(*(uint8_t*)0x20000f29 = (uint8_t)0x0);
(*(uint8_t*)0x20000f2a = (uint8_t)0x0);
(*(uint8_t*)0x20000f2b = (uint8_t)0x0);
(*(uint8_t*)0x20000f2c = (uint8_t)0x0);
(*(uint8_t*)0x20000f2d = (uint8_t)0x0);
(*(uint8_t*)0x20000f2e = (uint8_t)0x0);
(*(uint8_t*)0x20000f2f = (uint8_t)0x0);
(*(uint8_t*)0x20000f30 = (uint8_t)0x0);
(*(uint8_t*)0x20000f31 = (uint8_t)0x0);
(*(uint8_t*)0x20000f32 = (uint8_t)0x0);
(*(uint8_t*)0x20000f33 = (uint8_t)0x0);
(*(uint8_t*)0x20000f34 = (uint8_t)0x0);
(*(uint8_t*)0x20000f35 = (uint8_t)0x0);
(*(uint8_t*)0x20000f36 = (uint8_t)0x0);
(*(uint8_t*)0x20000f37 = (uint8_t)0xaa);
(*(uint16_t*)0x20000f38 = (uint16_t)0x204e);
(*(uint16_t*)0x20000f3a = (uint16_t)0x0);
(*(uint16_t*)0x20000f3c = (uint16_t)0x204e);
(*(uint16_t*)0x20000f3e = (uint16_t)0x0);
(*(uint16_t*)0x20000f40 = (uint16_t)0xa);
(*(uint8_t*)0x20000f42 = (uint8_t)0x0);
(*(uint8_t*)0x20000f43 = (uint8_t)0x0);
(*(uint8_t*)0x20000f44 = (uint8_t)0x0);
(*(uint32_t*)0x20000f48 = (uint32_t)0x0);
(*(uint32_t*)0x20000f4c = (uint32_t)0x0);
(*(uint64_t*)0x20000f50 = (uint64_t)0x0);
(*(uint64_t*)0x20000f58 = (uint64_t)0x0);
(*(uint64_t*)0x20000f60 = (uint64_t)0x0);
(*(uint64_t*)0x20000f68 = (uint64_t)0x0);
(*(uint64_t*)0x20000f70 = (uint64_t)0x0);
(*(uint64_t*)0x20000f78 = (uint64_t)0x0);
(*(uint64_t*)0x20000f80 = (uint64_t)0x0);
(*(uint64_t*)0x20000f88 = (uint64_t)0x0);
(*(uint64_t*)0x20000f90 = (uint64_t)0x0);
(*(uint64_t*)0x20000f98 = (uint64_t)0x0);
(*(uint64_t*)0x20000fa0 = (uint64_t)0x0);
(*(uint64_t*)0x20000fa8 = (uint64_t)0x0);
(*(uint32_t*)0x20000fb0 = (uint32_t)0x0);
(*(uint32_t*)0x20000fb4 = (uint32_t)0x0);
(*(uint8_t*)0x20000fb8 = (uint8_t)0x1);
(*(uint8_t*)0x20000fb9 = (uint8_t)0x0);
(*(uint8_t*)0x20000fba = (uint8_t)0x0);
(*(uint8_t*)0x20000fbb = (uint8_t)0x0);
(*(uint64_t*)0x20000fc0 = (uint64_t)0x0);
(*(uint64_t*)0x20000fc8 = (uint64_t)0x100000000000000);
(*(uint32_t*)0x20000fd0 = (uint32_t)0x0);
(*(uint8_t*)0x20000fd4 = (uint8_t)0x0);
(*(uint16_t*)0x20000fd8 = (uint16_t)0x0);
(*(uint32_t*)0x20000fdc = (uint32_t)0x0);
(*(uint32_t*)0x20000fec = (uint32_t)0x0);
(*(uint8_t*)0x20000ff0 = (uint8_t)0x0);
(*(uint8_t*)0x20000ff1 = (uint8_t)0x0);
(*(uint8_t*)0x20000ff2 = (uint8_t)0xff);
(*(uint32_t*)0x20000ff4 = (uint32_t)0x0);
(*(uint32_t*)0x20000ff8 = (uint32_t)0x0);
(*(uint32_t*)0x20000ffc = (uint32_t)0x0);
r[75] = execute_syscall(__NR_setsockopt, r[1], 0x29ul, 0x23ul,
0x20000f18ul, 0xe8ul, 0, 0, 0, 0);
(*(uint16_t*)0x20013ff0 = (uint16_t)0x2);
(*(uint16_t*)0x20013ff2 = (uint16_t)0x214e);
(*(uint8_t*)0x20013ff4 = (uint8_t)0xac);
(*(uint8_t*)0x20013ff5 = (uint8_t)0x14);
(*(uint8_t*)0x20013ff6 = (uint8_t)0x0);
(*(uint8_t*)0x20013ff7 = (uint8_t)0xaa);
(*(uint8_t*)0x20013ff8 = (uint8_t)0x0);
(*(uint8_t*)0x20013ff9 = (uint8_t)0x0);
(*(uint8_t*)0x20013ffa = (uint8_t)0x0);
(*(uint8_t*)0x20013ffb = (uint8_t)0x0);
(*(uint8_t*)0x20013ffc = (uint8_t)0x0);
(*(uint8_t*)0x20013ffd = (uint8_t)0x0);
(*(uint8_t*)0x20013ffe = (uint8_t)0x0);
(*(uint8_t*)0x20013fff = (uint8_t)0x0);
r[90] = execute_syscall(__NR_sendto, r[1], 0x20001000ul, 0x0ul,
0x20000000ul, 0x20013ff0ul, 0x10ul, 0, 0, 0);
}