Messages in this thread | | | From | Andrey Konovalov <> | Date | Fri, 2 Dec 2016 13:43:55 +0100 | Subject | net/can: warning in raw_setsockopt/__alloc_pages_slowpath |
| |
Hi!
I've got the following error report while running the syzkaller fuzzer.
A reproducer is attached.
On commit d8e435f3ab6fea2ea324dce72b51dd7761747523 (Nov 26).
------------[ cut here ]------------ WARNING: CPU: 0 PID: 4009 at mm/page_alloc.c:3511 __alloc_pages_slowpath+0x3d4/0x1bf0 Modules linked in: CPU: 0 PID: 4009 Comm: a.out Not tainted 4.9.0-rc6+ #54 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 ffff88006832f8a8 ffffffff81c73b14 0000000000000000 0000000000000000 ffffffff842c6320 0000000000000000 ffff88006832f8f0 ffffffff8123dc57 ffff880067d86000 ffffffff00000db7 ffffffff842c6320 0000000000000db7 Call Trace: [< inline >] __dump_stack lib/dump_stack.c:15 [<ffffffff81c73b14>] dump_stack+0xb3/0x10f lib/dump_stack.c:51 [<ffffffff8123dc57>] __warn+0x1a7/0x1f0 kernel/panic.c:550 [<ffffffff8123de6c>] warn_slowpath_null+0x2c/0x40 kernel/panic.c:585 [<ffffffff81559b04>] __alloc_pages_slowpath+0x3d4/0x1bf0 mm/page_alloc.c:3511 [<ffffffff8155b8e2>] __alloc_pages_nodemask+0x5c2/0x710 mm/page_alloc.c:3781 [<ffffffff816236a4>] alloc_pages_current+0xf4/0x400 mm/mempolicy.c:2072 [< inline >] alloc_pages ./include/linux/gfp.h:469 [<ffffffff815a834f>] kmalloc_order+0x1f/0x70 mm/slab_common.c:1015 [<ffffffff815a83bf>] kmalloc_order_trace+0x1f/0x160 mm/slab_common.c:1026 [< inline >] kmalloc_large ./include/linux/slab.h:422 [<ffffffff81635e67>] __kmalloc_track_caller+0x227/0x2a0 mm/slub.c:4233 [<ffffffff8159932c>] memdup_user+0x2c/0xa0 mm/util.c:137 [<ffffffff8369e0de>] raw_setsockopt+0x1be/0x9f0 net/can/raw.c:506 [< inline >] SYSC_setsockopt net/socket.c:1757 [<ffffffff82ca10c4>] SyS_setsockopt+0x154/0x240 net/socket.c:1736 [<ffffffff840f2901>] entry_SYSCALL_64_fastpath+0x1f/0xc2 arch/x86/entry/entry_64.S:209 ---[ end trace bc80556cca970089 ]--- // autogenerated by syzkaller (http://github.com/google/syzkaller)
#ifndef __NR_setsockopt #define __NR_setsockopt 54 #endif #ifndef __NR_socket #define __NR_socket 41 #endif
#define _GNU_SOURCE
#include <sys/ioctl.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/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 <stddef.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h>
const int kFailStatus = 67; const int kErrorStatus = 68; const int kRetryStatus = 69;
__attribute__((noreturn)) void fail(const char* msg, ...) { int e = errno; fflush(stdout); va_list args; va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); fprintf(stderr, " (errno %d)\n", e); exit(kFailStatus); }
__attribute__((noreturn)) void exitf(const char* msg, ...) { int e = errno; fflush(stdout); va_list args; va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); fprintf(stderr, " (errno %d)\n", e); exit(kRetryStatus); }
static int flag_debug;
void debug(const char* msg, ...) { if (!flag_debug) return; va_list args; va_start(args, msg); vfprintf(stdout, msg, args); va_end(args); fflush(stdout); }
__thread int skip_segv; __thread jmp_buf segv_env;
static void segv_handler(int sig, siginfo_t* info, void* uctx) { if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED)) _longjmp(segv_env, 1); exit(sig); }
static void install_segv_handler() { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = segv_handler; sa.sa_flags = SA_NODEFER | SA_SIGINFO; sigaction(SIGSEGV, &sa, NULL); sigaction(SIGBUS, &sa, NULL); }
#define NONFAILING(...) \ { \ __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ if (_setjmp(segv_env) == 0) { \ __VA_ARGS__; \ } \ __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ }
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); } }
static void setup_main_process(uint64_t pid) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = SIG_IGN; syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8); syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8); install_segv_handler();
char tmpdir_template[] = "./syzkaller.XXXXXX"; char* tmpdir = mkdtemp(tmpdir_template); if (!tmpdir) fail("failed to mkdtemp"); if (chmod(tmpdir, 0777)) fail("failed to chmod"); if (chdir(tmpdir)) fail("failed to chdir"); }
static void loop();
static void sandbox_common() { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setpgrp(); setsid();
struct rlimit rlim; rlim.rlim_cur = rlim.rlim_max = 128 << 20; setrlimit(RLIMIT_AS, &rlim); rlim.rlim_cur = rlim.rlim_max = 1 << 20; setrlimit(RLIMIT_FSIZE, &rlim); rlim.rlim_cur = rlim.rlim_max = 1 << 20; setrlimit(RLIMIT_STACK, &rlim); rlim.rlim_cur = rlim.rlim_max = 0; setrlimit(RLIMIT_CORE, &rlim);
unshare(CLONE_NEWNS); unshare(CLONE_NEWIPC); unshare(CLONE_IO); }
static int do_sandbox_none() { int pid = fork(); if (pid) return pid; sandbox_common(); loop(); exit(1); }
long r[2]; void loop() { memset(r, -1, sizeof(r)); r[0] = execute_syscall(__NR_socket, 0x1dul, 0x3ul, 0x1ul, 0, 0, 0, 0, 0, 0); r[1] = execute_syscall(__NR_setsockopt, r[0], 0x65ul, 0x1ul, 0x20000000ul, 0x18000000ul, 0, 0, 0, 0); } int main() { setup_main_process(0); int pid = do_sandbox_none(); int status = 0; while (waitpid(pid, &status, __WALL) != pid) { } return 0; }
| |