net: warning in inet_sock_destruct

From: Andrey Konovalov
Date: Mon Feb 20 2017 - 08:13:05 EST


Hi,

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

On commit c470abd4fde40ea6a0846a2beab642a578c0b8cd (4.10).

A reproducer and .config are attached.

------------[ cut here ]------------
WARNING: CPU: 2 PID: 4776 at net/ipv4/af_inet.c:152
inet_sock_destruct+0x7c7/0x9d0 net/ipv4/af_inet.c:152
Kernel panic - not syncing: panic_on_warn set ...

CPU: 2 PID: 4776 Comm: syz-executor0 Not tainted 4.10.0-rc8+ #201
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
<IRQ>
__dump_stack lib/dump_stack.c:15 [inline]
dump_stack+0x292/0x398 lib/dump_stack.c:51
panic+0x1cb/0x3a9 kernel/panic.c:179
__warn+0x1c4/0x1e0 kernel/panic.c:539
warn_slowpath_null+0x2c/0x40 kernel/panic.c:582
inet_sock_destruct+0x7c7/0x9d0 net/ipv4/af_inet.c:152
__sk_destruct+0xe1/0x6e0 net/core/sock.c:1430
__rcu_reclaim kernel/rcu/rcu.h:118 [inline]
rcu_do_batch.isra.67+0x900/0xc50 kernel/rcu/tree.c:2780
invoke_rcu_callbacks kernel/rcu/tree.c:3043 [inline]
__rcu_process_callbacks kernel/rcu/tree.c:3010 [inline]
rcu_process_callbacks+0x2b7/0xba0 kernel/rcu/tree.c:3027
__do_softirq+0x2fb/0xb7d kernel/softirq.c:284
invoke_softirq kernel/softirq.c:364 [inline]
irq_exit+0x19e/0x1d0 kernel/softirq.c:405
exiting_irq arch/x86/include/asm/apic.h:658 [inline]
smp_apic_timer_interrupt+0x76/0xa0 arch/x86/kernel/apic/apic.c:961
apic_timer_interrupt+0x93/0xa0 arch/x86/entry/entry_64.S:487
RIP: 0010:lock_is_held_type+0x21/0x280 kernel/locking/lockdep.c:3780
RSP: 0018:ffff88006b4af8c0 EFLAGS: 00000246 ORIG_RAX: ffffffffffffff10
RAX: 0000000000000001 RBX: ffff88006b4af7a0 RCX: 1ffff1000d695ef8
RDX: dffffc0000000000 RSI: 00000000ffffffff RDI: ffffffff8590c900
RBP: ffff88006b4af8e8 R08: ffffed000d695fde R09: ffffed000d695fde
R10: 0000000000000002 R11: ffffed000d695fdd R12: ffff88006b4afd18
R13: 0000000000000000 R14: ffffffff8590c900 R15: 0000000000000071
</IRQ>
lock_is_held include/linux/lockdep.h:348 [inline]
___might_sleep+0x5aa/0x640 kernel/sched/core.c:7748
__might_sleep+0x95/0x1a0 kernel/sched/core.c:7739
__might_fault+0x15b/0x290 mm/memory.c:4080
__copy_from_user arch/x86/include/asm/uaccess_64.h:113 [inline]
_copy_from_user+0xc1/0x120 arch/x86/lib/usercopy.c:80
copy_from_user arch/x86/include/asm/uaccess.h:702 [inline]
SYSC_nanosleep kernel/time/hrtimer.c:1581 [inline]
SyS_nanosleep+0xab/0x1a0 kernel/time/hrtimer.c:1576
entry_SYSCALL_64_fastpath+0x1f/0xc2
RIP: 0033:0x46f650
RSP: 002b:00007ffe30b79c78 EFLAGS: 00000246 ORIG_RAX: 0000000000000023
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 000000000046f650
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00007ffe30b79c80
RBP: 00000000000057cd R08: 00000000000012a8 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 000000000002aa4d
R13: 00000000000057cd R14: 000000000000001f R15: 000000000002a99d
Dumping ftrace buffer:
(ftrace buffer empty)
Kernel Offset: disabled
Rebooting in 86400 seconds..
// autogenerated by syzkaller (http://github.com/google/syzkaller)

#ifndef __NR_mmap
#define __NR_mmap 9
#endif
#ifndef __NR_socket
#define __NR_socket 41
#endif
#ifndef __NR_bind
#define __NR_bind 49
#endif
#ifndef __NR_sendto
#define __NR_sendto 44
#endif
#ifndef __NR_connect
#define __NR_connect 42
#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>

#define NONFAILING(x) x

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[30];

void main()
{
memset(r, -1, sizeof(r));
r[0] = execute_syscall(__NR_mmap, 0x20000000ul, 0x1a000ul, 0x3ul,
0x32ul, 0xfffffffffffffffful, 0x0ul, 0, 0, 0);
r[1] = execute_syscall(__NR_socket, 0xaul, 0x2ul, 0x0ul, 0, 0, 0, 0,
0, 0);
NONFAILING(*(uint16_t*)0x20005000 = (uint16_t)0xa);
NONFAILING(*(uint16_t*)0x20005002 = (uint16_t)0x204e);
NONFAILING(*(uint32_t*)0x20005004 = (uint32_t)0x0);
NONFAILING(*(uint64_t*)0x20005008 = (uint64_t)0x0);
NONFAILING(*(uint64_t*)0x20005010 = (uint64_t)0x0);
NONFAILING(*(uint32_t*)0x20005018 = (uint32_t)0x0);
r[8] = execute_syscall(__NR_bind, r[1], 0x20005000ul, 0x20ul, 0, 0, 0,
0, 0, 0);
NONFAILING(*(uint16_t*)0x2000b000 = (uint16_t)0xa);
NONFAILING(*(uint16_t*)0x2000b002 = (uint16_t)0x204e);
NONFAILING(*(uint32_t*)0x2000b004 = (uint32_t)0x0);
NONFAILING(*(uint64_t*)0x2000b008 = (uint64_t)0x0);
NONFAILING(*(uint64_t*)0x2000b010 = (uint64_t)0x0);
NONFAILING(*(uint32_t*)0x2000b018 = (uint32_t)0x0);
r[15] = execute_syscall(__NR_sendto, r[1], 0x20013000ul, 0x0ul,
0x20000800ul, 0x2000b000ul, 0x20ul, 0, 0, 0);
NONFAILING(*(uint16_t*)0x20017ff0 = (uint16_t)0x2);
NONFAILING(*(uint16_t*)0x20017ff2 = (uint16_t)0x204e);
NONFAILING(*(uint32_t*)0x20017ff4 = (uint32_t)0x100007f);
NONFAILING(*(uint8_t*)0x20017ff8 = (uint8_t)0x0);
NONFAILING(*(uint8_t*)0x20017ff9 = (uint8_t)0x0);
NONFAILING(*(uint8_t*)0x20017ffa = (uint8_t)0x0);
NONFAILING(*(uint8_t*)0x20017ffb = (uint8_t)0x0);
NONFAILING(*(uint8_t*)0x20017ffc = (uint8_t)0x0);
NONFAILING(*(uint8_t*)0x20017ffd = (uint8_t)0x0);
NONFAILING(*(uint8_t*)0x20017ffe = (uint8_t)0x0);
NONFAILING(*(uint8_t*)0x20017fff = (uint8_t)0x0);
r[27] = execute_syscall(__NR_connect, r[1], 0x20017ff0ul, 0x10ul, 0,
0, 0, 0, 0, 0);
NONFAILING(*(uint32_t*)0x20005000 = (uint32_t)0x2);
r[29] = execute_syscall(__NR_setsockopt, r[1], 0x29ul, 0x1ul,
0x20005000ul, 0x4ul, 0, 0, 0, 0);

return 0;
}

Attachment: .config
Description: Binary data