// https://syzkaller.appspot.com/bug?id=e3984ac2adcafab62c3c67c002e6c16b759f7c1f // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include static bool write_file(const char* file, const char* what, ...) { char buf[1024]; va_list args; va_start(args, what); vsnprintf(buf, sizeof(buf), what, args); va_end(args); buf[sizeof(buf) - 1] = 0; int len = strlen(buf); int fd = open(file, O_WRONLY | O_CLOEXEC); if (fd == -1) return false; if (write(fd, buf, len) != len) { int err = errno; close(fd); errno = err; return false; } close(fd); return true; } static int inject_fault(int nth) { int fd; fd = open("/proc/thread-self/fail-nth", O_RDWR); if (fd == -1) exit(1); char buf[16]; sprintf(buf, "%d", nth); if (write(fd, buf, strlen(buf)) != (ssize_t)strlen(buf)) exit(1); return fd; } static const char* setup_fault() { int fd = open("/proc/self/make-it-fail", O_WRONLY); if (fd == -1) return "CONFIG_FAULT_INJECTION is not enabled"; close(fd); fd = open("/proc/thread-self/fail-nth", O_WRONLY); if (fd == -1) return "kernel does not have systematic fault injection support"; close(fd); static struct { const char* file; const char* val; bool fatal; } files[] = { {"/sys/kernel/debug/failslab/ignore-gfp-wait", "N", true}, {"/sys/kernel/debug/fail_futex/ignore-private", "N", false}, {"/sys/kernel/debug/fail_page_alloc/ignore-gfp-highmem", "N", false}, {"/sys/kernel/debug/fail_page_alloc/ignore-gfp-wait", "N", false}, {"/sys/kernel/debug/fail_page_alloc/min-order", "0", false}, }; unsigned i; for (i = 0; i < sizeof(files) / sizeof(files[0]); i++) { if (!write_file(files[i].file, files[i].val)) { if (files[i].fatal) return "failed to write fault injection file"; } } return NULL; } uint64_t r[1] = {0xffffffffffffffff}; int main(void) { syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul); const char* reason; (void)reason; if ((reason = setup_fault())) printf("the reproducer may not work as expected: fault injection setup " "failed: %s\n", reason); intptr_t res = 0; if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { } // openat$dm_control arguments: [ // fd: const = 0xffffffffffffff9c (8 bytes) // file: ptr[in, buffer] { // buffer: {2f 64 65 76 2f 6d 61 70 70 65 72 2f 63 6f 6e 74 72 6f 6c 00} // (length 0x14) // } // flags: open_flags = 0x802 (4 bytes) // mode: const = 0x0 (2 bytes) // ] // returns fd_dm_ctl memcpy((void*)0x200000000440, "/dev/mapper/control\000", 20); res = syscall(__NR_openat, /*fd=*/0xffffffffffffff9cul, /*file=*/0x200000000440ul, /*flags=O_NONBLOCK|O_RDWR*/ 0x802, /*mode=*/0); if (res != -1) r[0] = res; // ioctl$DM_DEV_CREATE arguments: [ // fd: fd_dm_ctl (resource) // cmd: const = 0xc138fd03 (4 bytes) // arg: ptr[inout, dm_ioctl_t[dm_id_create, void, const[0, int32], const[0, // int32]]] { // dm_ioctl_t[dm_id_create, void, const[0, int32], const[0, int32]] { // version_major: const = 0x4 (4 bytes) // version_minor: const = 0x0 (4 bytes) // version_patch: const = 0x0 (4 bytes) // data_size: bytesize = 0x138 (4 bytes) // data_start: offsetof = 0x138 (4 bytes) // target_count: const = 0x0 (4 bytes) // open_count: const = 0x0 (4 bytes) // flags: dm_ioctl_flags = 0x20000 (4 bytes) // event_nr: const = 0x0 (4 bytes) // padding: const = 0x0 (4 bytes) // id: dm_id_create { // dev: dm_dev_number (resource) // name: dm_dev_name { // prefix: buffer: {73 79 7a} (length 0x3) // proc: proc = 0x0 (1 bytes) // slot: buffer: {32 00} (length 0x2) // pad = 0x0 (122 bytes) // } // uuid: union dm_dev_uuid_opt { // uuid: dm_dev_uuid { // prefix: buffer: {43 52 50 2d 73 79 7a} (length 0x7) // proc: proc = 0x0 (1 bytes) // slot: buffer: {31 00} (length 0x2) // pad = 0x0 (126 bytes) // } // } // } // data: buffer: {} (length 0x0) // } // } // ] *(uint32_t*)0x200000000500 = 4; *(uint32_t*)0x200000000504 = 0; *(uint32_t*)0x200000000508 = 0; *(uint32_t*)0x20000000050c = 0x138; *(uint32_t*)0x200000000510 = 0x138; *(uint32_t*)0x200000000514 = 0; *(uint32_t*)0x200000000518 = 0; *(uint32_t*)0x20000000051c = 0x20000; *(uint32_t*)0x200000000520 = 0; *(uint32_t*)0x200000000524 = 0; memcpy((void*)0x200000000530, "syz", 3); *(uint8_t*)0x200000000533 = 0x61; memcpy((void*)0x200000000534, "2\000", 2); memcpy((void*)0x2000000005b0, "CRP-syz", 7); *(uint8_t*)0x2000000005b7 = 0x61; memcpy((void*)0x2000000005b8, "1\000", 2); syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0xc138fd03, /*arg=*/0x200000000500ul); // ioctl$DM_TARGET_MSG arguments: [ // fd: fd_dm_ctl (resource) // cmd: const = 0xc138fd0e (4 bytes) // arg: ptr[inout, dm_ioctl_t[dm_id_lookup, dm_target_msg, const[0, int32], // const[0, int32]]] { // dm_ioctl_t[dm_id_lookup, dm_target_msg, const[0, int32], const[0, // int32]] { // version_major: const = 0x4 (4 bytes) // version_minor: const = 0x0 (4 bytes) // version_patch: const = 0x0 (4 bytes) // data_size: bytesize = 0x180 (4 bytes) // data_start: offsetof = 0x138 (4 bytes) // target_count: const = 0x0 (4 bytes) // open_count: const = 0x0 (4 bytes) // flags: dm_ioctl_flags = 0xa0200 (4 bytes) // event_nr: const = 0x0 (4 bytes) // padding: const = 0x0 (4 bytes) // id: union dm_id_lookup { // by_name: dm_id_by_name { // dev: dm_dev_number (resource) // name: dm_dev_name { // prefix: buffer: {73 79 7a} (length 0x3) // proc: proc = 0x0 (1 bytes) // slot: buffer: {32 00} (length 0x2) // pad = 0x0 (122 bytes) // } // pad = 0x0 (136 bytes) // } // } // data: dm_target_msg { // sector: dm_sectors = 0x1000 (8 bytes) // message: union dm_message { // stats_create: dm_stats_create { // cmd: buffer: {40 73 74 61 74 73 5f 63 72 65 61 74 65 20} // (length 0xe) range: buffer: {31 30 32 34 2b 34 30 39 36} // (length 0x9) sp: const = 0x20 (1 bytes) step: buffer: {2f 31 // 36} (length 0x3) opts: buffer: {20 32 20 70 72 65 63 69 73 65 // 5f 74 69 6d 65 73 74 61 6d 70 73 20 68 69 73 74 6f 67 72 61 6d // 3a 31 2c 32} (length 0x23) // } // } // z: const = 0x0 (1 bytes) // } // } // } // ] *(uint32_t*)0x200000000640 = 4; *(uint32_t*)0x200000000644 = 0; *(uint32_t*)0x200000000648 = 0; *(uint32_t*)0x20000000064c = 0x180; *(uint32_t*)0x200000000650 = 0x138; *(uint32_t*)0x200000000654 = 0; *(uint32_t*)0x200000000658 = 0; *(uint32_t*)0x20000000065c = 0xa0200; *(uint32_t*)0x200000000660 = 0; *(uint32_t*)0x200000000664 = 0; memcpy((void*)0x200000000670, "syz", 3); *(uint8_t*)0x200000000673 = 0x61; memcpy((void*)0x200000000674, "2\000", 2); *(uint64_t*)0x200000000778 = 0x1000; memcpy((void*)0x200000000780, "@stats_create ", 14); memcpy((void*)0x20000000078e, "1024+4096", 9); *(uint8_t*)0x200000000797 = 0x20; memcpy((void*)0x200000000798, "/16", 3); memcpy((void*)0x20000000079b, " 2 precise_timestamps histogram:1,2", 35); *(uint8_t*)0x2000000007be = 0; inject_fault(9); syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/0xc138fd0e, /*arg=*/0x200000000640ul); return 0; }