Kernel WARNING in dio_complete found by syzkaller

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

 



Kernel version: 4.14.0
Kernel configure: defconfig
syzkaller crepro:
// autogenerated by syzkaller (http://github.com/google/syzkaller)

#define _GNU_SOURCE
#include <endian.h>
#include <linux/futex.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>

__attribute__((noreturn)) static void doexit(int status)
{
  volatile unsigned i;
  syscall(__NR_exit_group, status);
  for (i = 0;; i++) {
  }
}
#include <setjmp.h>
#include <signal.h>
#include <stdint.h>
#include <string.h>
#include <string.h>

static __thread int skip_segv;
static __thread jmp_buf segv_env;

static void segv_handler(int sig, siginfo_t* info, void* uctx)
{
  uintptr_t addr = (uintptr_t)info->si_addr;
  const uintptr_t prog_start = 1 << 20;
  const uintptr_t prog_end = 100 << 20;
  if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) &&
      (addr < prog_start || addr > prog_end)) {
    _longjmp(segv_env, 1);
  }
  doexit(sig);
}

static void install_segv_handler()
{
  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);

  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 void test();

void loop()
{
  while (1) {
    test();
  }
}

struct thread_t {
  int created, running, call;
  pthread_t th;
};

static struct thread_t threads[16];
static void execute_call(int call);
static int running;
static int collide;

static void* thr(void* arg)
{
  struct thread_t* th = (struct thread_t*)arg;
  for (;;) {
    while (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE))
      syscall(SYS_futex, &th->running, FUTEX_WAIT, 0, 0);
    execute_call(th->call);
    __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
    __atomic_store_n(&th->running, 0, __ATOMIC_RELEASE);
    syscall(SYS_futex, &th->running, FUTEX_WAKE);
  }
  return 0;
}

static void execute(int num_calls)
{
  int call, thread;
  running = 0;
  for (call = 0; call < num_calls; call++) {
    for (thread = 0; thread < sizeof(threads) / sizeof(threads[0]); thread++) {
      struct thread_t* th = &threads[thread];
      if (!th->created) {
        th->created = 1;
        pthread_attr_t attr;
        pthread_attr_init(&attr);
        pthread_attr_setstacksize(&attr, 128 << 10);
        pthread_create(&th->th, &attr, thr, th);
      }
      if (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE)) {
        th->call = call;
        __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
        __atomic_store_n(&th->running, 1, __ATOMIC_RELEASE);
        syscall(SYS_futex, &th->running, FUTEX_WAKE);
        if (collide && call % 2)
          break;
        struct timespec ts;
        ts.tv_sec = 0;
        ts.tv_nsec = 20 * 1000 * 1000;
        syscall(SYS_futex, &th->running, FUTEX_WAIT, 1, &ts);
        if (running)
          usleep((call == num_calls - 1) ? 10000 : 1000);
        break;
      }
    }
  }
}

long r[2];
uint64_t procid;
void execute_call(int call)
{
  switch (call) {
  case 0:
    syscall(__NR_mmap, 0x20000000, 0x1000, 3, 0x32, -1, 0);
    break;
  case 1:
    NONFAILING(memcpy(
        (void*)0x20000ffe,
        "\x2f\x72\x6f\x6f\x74\x2f\x74\x65\x73\x74\x2e\x74\x78\x74\x00\x00\x00",
        17));
    r[0] = syscall(__NR_open, 0x20000ffe, 0x403e, 0);
    break;
  case 2:
    syscall(__NR_mmap, 0x20001000, 0x1000, 3, 0x32, -1, 0);
    break;
  case 3:
    syscall(__NR_write, -1, 0x20001000, 0);
    break;
  case 4:
    syscall(__NR_mmap, 0x20000000, 0x2000, 2, 0x11, r[0], 0);
    break;
  case 5:
    NONFAILING(memcpy((void*)0x20000fef, "/root/tmp/test.c", 17));
    syscall(__NR_open, 0x20000fef, 0, 0);
    break;
  case 6:
    syscall(__NR_mmap, 0x20002000, 0x1000, 3, 0x32, -1, 0);
    break;
  case 7:
    NONFAILING(memcpy(
        (void*)0x20000ffe,
        "\x2f\x72\x6f\x6f\x74\x2f\x74\x65\x73\x74\x2e\x74\x78\x74\x00\x00\x00",
        17));
    r[1] = syscall(__NR_open, 0x20000ffe, 0, 0);
    break;
  case 8:
    syscall(__NR_close, r[1]);
    break;
  case 9:
    NONFAILING(memcpy(
        (void*)0x20000ffe,
        "\x2f\x72\x6f\x6f\x74\x2f\x74\x65\x73\x74\x2e\x74\x78\x74\x00\x00\x00",
        17));
    syscall(__NR_open, 0x20000ffe, 0x403e, 0);
    break;
  case 10:
    syscall(__NR_write, r[1], 0x20002000, 0xfffffe7f);
    break;
  }
}

void test()
{
  memset(r, -1, sizeof(r));
  execute(11);
  collide = 1;
  execute(11);
}

int main()
{
  for (procid = 0; procid < 8; procid++) {
    if (fork() == 0) {
      install_segv_handler();
      for (;;) {
        loop();
      }
    }
  }
  sleep(1000000);
  return 0;
}

log:
------------[ cut here ]------------
WARNING: CPU: 0 PID: 6473 at
/root/linux-source-4.14/fs/direct-io.c:293 dio_complete+0x58e/0x840
Kernel panic - not syncing: panic_on_warn set ...

CPU: 0 PID: 6473 Comm: syz-executor0 Not tainted 4.14.7 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
Call Trace:
 dump_stack+0x83/0xb8
 panic+0x1bc/0x3b1
 __warn+0x1c9/0x1e0
 report_bug+0x213/0x2d0
 fixup_bug.part.12+0x3c/0x90
 do_error_trap+0x65/0xb0
 do_invalid_op+0x20/0x30
 invalid_op+0x18/0x20
RIP: 0010:dio_complete+0x58e/0x840
RSP: 0018:ffff880065e1f5c8 EFLAGS: 00010287
RAX: 0000000000010000 RBX: ffff880037e14340 RCX: ffffc90000576000
RDX: 0000000000002359 RSI: ffffffff8176382e RDI: ffff880062e4166c
RBP: ffff880065e1f610 R08: ffff880065e1f430 R09: ffff88003d8013c0
R10: ffff880065e1f117 R11: ffffed000cbc3e23 R12: ffff880062e417d8
R13: 0000000000001000 R14: 0000000000000000 R15: 0000000000001000
 do_blockdev_direct_IO+0x6239/0x7f90
 __blockdev_direct_IO+0xa2/0xd0
 ext4_direct_IO+0x7b5/0x1290 [ext4]
 generic_file_direct_write+0x22a/0x420
 __generic_file_write_iter+0x227/0x5b0
 ext4_file_write_iter+0x2d5/0xf00 [ext4]
 new_sync_write+0x3d5/0x5f0
 __vfs_write+0xe8/0x120
 vfs_write+0x18c/0x500
 SyS_write+0xd8/0x1b0
 system_call_fast_compare_end+0xc/0x97
RIP: 0033:0x452f39
RSP: 002b:00007fda76cb7c68 EFLAGS: 00000216 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 000000000070bea0 RCX: 0000000000452f39
RDX: 0000000000001000 RSI: 0000000020000000 RDI: 0000000000000013
RBP: 0000000000000652 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000216 R12: 00000000006de850
R13: 00000000ffffffff R14: 00007fda76cb86d4 R15: 000000000049f371
Dumping ftrace buffer:
   (ftrace buffer empty)
Kernel Offset: disabled



[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]

  Powered by Linux