// https://syzkaller.appspot.com/bug?id=ffc67b754663402f65e6ef2fc7325307a4581338 // 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 #include #include #include static __thread int clone_ongoing; static __thread int skip_segv; static __thread jmp_buf segv_env; static void segv_handler(int sig, siginfo_t* info, void* ctx) { if (__atomic_load_n(&clone_ongoing, __ATOMIC_RELAXED) != 0) { exit(sig); } uintptr_t addr = (uintptr_t)info->si_addr; const uintptr_t prog_start = 1 << 20; const uintptr_t prog_end = 100 << 20; int skip = __atomic_load_n(&skip_segv, __ATOMIC_RELAXED) != 0; int valid = addr < prog_start || addr > prog_end; if (skip && valid) { _longjmp(segv_env, 1); } exit(sig); } static void install_segv_handler(void) { 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(...) \ ({ \ int ok = 1; \ __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); \ if (_setjmp(segv_env) == 0) { \ __VA_ARGS__; \ } else \ ok = 0; \ __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); \ ok; \ }) static void use_temporary_dir(void) { char tmpdir_template[] = "./syzkaller.XXXXXX"; char* tmpdir = mkdtemp(tmpdir_template); if (!tmpdir) exit(1); if (chmod(tmpdir, 0777)) exit(1); if (chdir(tmpdir)) exit(1); } 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 long syz_open_dev(volatile long a0, volatile long a1, volatile long a2) { if (a0 == 0xc || a0 == 0xb) { char buf[128]; sprintf(buf, "/dev/%s/%d:%d", a0 == 0xc ? "char" : "block", (uint8_t)a1, (uint8_t)a2); return open(buf, O_RDWR, 0); } else { unsigned long nb = a1; char buf[1024]; char* hash; strncpy(buf, (char*)a0, sizeof(buf) - 1); buf[sizeof(buf) - 1] = 0; while ((hash = strchr(buf, '#'))) { *hash = '0' + (char)(nb % 10); nb /= 10; } return open(buf, a2 & ~O_CREAT, 0); } } static void setup_sysctl() { int cad_pid = fork(); if (cad_pid < 0) exit(1); if (cad_pid == 0) { for (;;) sleep(100); } char tmppid[32]; snprintf(tmppid, sizeof(tmppid), "%d", cad_pid); struct { const char* name; const char* data; } files[] = { {"/sys/kernel/debug/x86/nmi_longest_ns", "10000000000"}, {"/proc/sys/kernel/hung_task_check_interval_secs", "20"}, {"/proc/sys/net/core/bpf_jit_kallsyms", "1"}, {"/proc/sys/net/core/bpf_jit_harden", "0"}, {"/proc/sys/kernel/kptr_restrict", "0"}, {"/proc/sys/kernel/softlockup_all_cpu_backtrace", "1"}, {"/proc/sys/fs/mount-max", "100"}, {"/proc/sys/vm/oom_dump_tasks", "0"}, {"/proc/sys/debug/exception-trace", "0"}, {"/proc/sys/kernel/printk", "7 4 1 3"}, {"/proc/sys/kernel/keys/gc_delay", "1"}, {"/proc/sys/vm/oom_kill_allocating_task", "1"}, {"/sys/kernel/debug/failslab/task-filter", "Y"}, {"/sys/kernel/debug/fail_page_alloc/task-filter", "Y"}, {"/sys/kernel/debug/fail_futex/task-filter", "Y"}, {"/sys/kernel/debug/fail_usercopy/task-filter", "Y"}, {"/sys/kernel/debug/fail_make_request/task-filter", "Y"}, {"/sys/kernel/debug/fail_io_timeout/task-filter", "Y"}, {"/sys/kernel/debug/fail_iommufd/task-filter", "Y"}, {"/proc/sys/kernel/ctrl-alt-del", "0"}, {"/proc/sys/kernel/cad_pid", tmppid}, }; for (size_t i = 0; i < sizeof(files) / sizeof(files[0]); i++) { if (!write_file(files[i].name, files[i].data)) { } } kill(cad_pid, SIGKILL); while (waitpid(cad_pid, NULL, 0) != cad_pid) ; } uint64_t r[3] = {0xffffffffffffffff, 0xffffffffffffffff, 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); setup_sysctl(); const char* reason; (void)reason; install_segv_handler(); use_temporary_dir(); intptr_t res = 0; if (write(1, "executing program\n", sizeof("executing program\n") - 1)) { } // openat arguments: [ // fd: fd_dir (resource) // file: ptr[in, buffer] { // buffer: {2e 2f 69 6d 67 00} (length 0x6) // } // flags: open_flags = 0x42 (4 bytes) // mode: open_mode = 0x1ff (2 bytes) // ] // returns fd NONFAILING(memcpy((void*)0x200000000100, "./img\000", 6)); res = syscall( __NR_openat, /*fd=*/0xffffff9c, /*file=*/0x200000000100ul, /*flags=O_CREAT|O_RDWR*/ 0x42, /*mode=S_IXOTH|S_IWOTH|S_IROTH|S_IXGRP|S_IWGRP|S_IRGRP|S_IXUSR|S_IWUSR|0x100*/ 0x1ff); if (res != -1) r[0] = res; // write arguments: [ // fd: fd (resource) // buf: ptr[in, buffer] { // buffer: {78 9c 92 6c 55 60 66 60 60 e0 f9 90 70 67 86 64 eb 03 46 06 // 06 06 c3 c3 0a 77 63 19 18 18 40 6c 10 60 02 11 9c 1c 0c 0c 0f f2 23 // e4 92 7b ec 77 a6 65 e6 a4 ea 25 e7 e7 a4 fc ff ff 5f b2 f5 01 48 3e // 2c 3c 2c b8 0c aa 96 91 81 a1 f1 2d 54 6f 0a 03 26 10 02 89 83 14 66 // 97 5c 99 2e 90 7c ff 5a 31 43 25 43 15 43 36 43 22 43 0e 43 0e 43 2a // 43 51 34 d8 5c 90 fd ba d7 15 1b 85 a0 6e 01 61 90 5b 19 58 59 18 18 // 42 e3 2c 4e ea 1f 5a 9e 07 72 8b 01 c2 1d 2e 4b de 2b d9 41 d5 31 32 // 30 38 be c5 62 3f 56 70 89 ab 7a 2d 16 3b 41 66 b2 80 ed e4 60 60 68 // 7d 7f 60 55 c4 d1 e9 3f 40 76 1a 22 ec f4 73 b1 3a ad 00 55 87 ec 77 // 2e 2c d6 70 c1 c4 1b ef 3c 4a 76 8a f4 b9 51 5c 59 95 9d 98 93 93 5a // 54 0c 36 8f 83 81 81 c1 60 a7 79 ff 2e 98 9f 19 d9 18 d8 ce 5a f1 7d // 6d 39 e4 94 54 91 58 52 52 64 c8 00 a1 20 f6 73 32 30 30 c8 6c eb 3f // f5 12 61 3f 03 d3 ad b5 1c 0f d0 cc 62 82 99 75 6b 4f c4 9a f7 1a a6 // 56 60 43 8c 20 66 19 61 37 0b ec f7 92 bc eb ac 58 c2 05 14 be ac b0 // 70 f1 67 e2 cd 39 78 e6 98 13 28 5c 8c 10 e1 92 32 bf 91 e9 1b 54 1d // 52 b8 28 6b 60 09 17 05 06 06 01 b0 85 e7 0b dc 2b 79 76 4d 5c c8 f0 // 1f 3f c4 62 07 13 6e 3b 04 30 ec e8 74 94 ca 27 d2 0e 9f 55 26 ab 78 // a0 76 30 e3 b6 03 94 04 18 38 18 18 98 35 40 9a 9c 0f f0 58 ed 3c f1 // 2e 0d 6a 96 3a 96 30 64 41 0e 43 a3 42 6e 93 6d a7 bf 5d 01 85 a1 f1 // 7f 8c f4 0f 0b 6f 36 98 7a a6 b0 ba cd 58 d2 7f 5c 64 ef 6d 17 a8 3a // a4 30 67 91 c2 12 e6 52 20 71 90 26 cd 1b f3 15 99 1e d7 bc c0 c8 87 // ff b3 ff a7 fe af fa 9f 23 88 d5 3d 20 3b d8 c1 ee e1 62 60 58 9d 7c // 29 00 4b de c8 e6 b7 93 4f 87 aa 63 64 60 58 f8 1f 6a b7 3a 16 f7 a8 // c3 c4 05 76 99 4e b8 ee 93 cb a1 5f 92 5b a0 5f 5c 59 a5 9b 99 9b 98 // 9e 9a 9e 9a 67 64 64 6c 66 60 62 60 60 6a a4 0f f6 37 84 fc 0f 08 00 // 00 ff ff ad 97 19 da} (length 0x243) // } // count: len = 0x1000 (8 bytes) // ] NONFAILING(memcpy( (void*)0x200000000200, "\x78\x9c\x92\x6c\x55\x60\x66\x60\x60\xe0\xf9\x90\x70\x67\x86\x64\xeb\x03" "\x46\x06\x06\x06\xc3\xc3\x0a\x77\x63\x19\x18\x18\x40\x6c\x10\x60\x02\x11" "\x9c\x1c\x0c\x0c\x0f\xf2\x23\xe4\x92\x7b\xec\x77\xa6\x65\xe6\xa4\xea\x25" "\xe7\xe7\xa4\xfc\xff\xff\x5f\xb2\xf5\x01\x48\x3e\x2c\x3c\x2c\xb8\x0c\xaa" "\x96\x91\x81\xa1\xf1\x2d\x54\x6f\x0a\x03\x26\x10\x02\x89\x83\x14\x66\x97" "\x5c\x99\x2e\x90\x7c\xff\x5a\x31\x43\x25\x43\x15\x43\x36\x43\x22\x43\x0e" "\x43\x0e\x43\x2a\x43\x51\x34\xd8\x5c\x90\xfd\xba\xd7\x15\x1b\x85\xa0\x6e" "\x01\x61\x90\x5b\x19\x58\x59\x18\x18\x42\xe3\x2c\x4e\xea\x1f\x5a\x9e\x07" "\x72\x8b\x01\xc2\x1d\x2e\x4b\xde\x2b\xd9\x41\xd5\x31\x32\x30\x38\xbe\xc5" "\x62\x3f\x56\x70\x89\xab\x7a\x2d\x16\x3b\x41\x66\xb2\x80\xed\xe4\x60\x60" "\x68\x7d\x7f\x60\x55\xc4\xd1\xe9\x3f\x40\x76\x1a\x22\xec\xf4\x73\xb1\x3a" "\xad\x00\x55\x87\xec\x77\x2e\x2c\xd6\x70\xc1\xc4\x1b\xef\x3c\x4a\x76\x8a" "\xf4\xb9\x51\x5c\x59\x95\x9d\x98\x93\x93\x5a\x54\x0c\x36\x8f\x83\x81\x81" "\xc1\x60\xa7\x79\xff\x2e\x98\x9f\x19\xd9\x18\xd8\xce\x5a\xf1\x7d\x6d\x39" "\xe4\x94\x54\x91\x58\x52\x52\x64\xc8\x00\xa1\x20\xf6\x73\x32\x30\x30\xc8" "\x6c\xeb\x3f\xf5\x12\x61\x3f\x03\xd3\xad\xb5\x1c\x0f\xd0\xcc\x62\x82\x99" "\x75\x6b\x4f\xc4\x9a\xf7\x1a\xa6\x56\x60\x43\x8c\x20\x66\x19\x61\x37\x0b" "\xec\xf7\x92\xbc\xeb\xac\x58\xc2\x05\x14\xbe\xac\xb0\x70\xf1\x67\xe2\xcd" "\x39\x78\xe6\x98\x13\x28\x5c\x8c\x10\xe1\x92\x32\xbf\x91\xe9\x1b\x54\x1d" "\x52\xb8\x28\x6b\x60\x09\x17\x05\x06\x06\x01\xb0\x85\xe7\x0b\xdc\x2b\x79" "\x76\x4d\x5c\xc8\xf0\x1f\x3f\xc4\x62\x07\x13\x6e\x3b\x04\x30\xec\xe8\x74" "\x94\xca\x27\xd2\x0e\x9f\x55\x26\xab\x78\xa0\x76\x30\xe3\xb6\x03\x94\x04" "\x18\x38\x18\x18\x98\x35\x40\x9a\x9c\x0f\xf0\x58\xed\x3c\xf1\x2e\x0d\x6a" "\x96\x3a\x96\x30\x64\x41\x0e\x43\xa3\x42\x6e\x93\x6d\xa7\xbf\x5d\x01\x85" "\xa1\xf1\x7f\x8c\xf4\x0f\x0b\x6f\x36\x98\x7a\xa6\xb0\xba\xcd\x58\xd2\x7f" "\x5c\x64\xef\x6d\x17\xa8\x3a\xa4\x30\x67\x91\xc2\x12\xe6\x52\x20\x71\x90" "\x26\xcd\x1b\xf3\x15\x99\x1e\xd7\xbc\xc0\xc8\x87\xff\xb3\xff\xa7\xfe\xaf" "\xfa\x9f\x23\x88\xd5\x3d\x20\x3b\xd8\xc1\xee\xe1\x62\x60\x58\x9d\x7c\x29" "\x00\x4b\xde\xc8\xe6\xb7\x93\x4f\x87\xaa\x63\x64\x60\x58\xf8\x1f\x6a\xb7" "\x3a\x16\xf7\xa8\xc3\xc4\x05\x76\x99\x4e\xb8\xee\x93\xcb\xa1\x5f\x92\x5b" "\xa0\x5f\x5c\x59\xa5\x9b\x99\x9b\x98\x9e\x9a\x9e\x9a\x67\x64\x64\x6c\x66" "\x60\x62\x60\x60\x6a\xa4\x0f\xf6\x37\x84\xfc\x0f\x08\x00\x00\xff\xff\xad" "\x97\x19\xda", 579)); syscall(__NR_write, /*fd=*/r[0], /*buf=*/0x200000000200ul, /*count=*/0x1000ul); // syz_open_dev$loop arguments: [ // dev: ptr[in, buffer] { // buffer: {2f 64 65 76 2f 6c 6f 6f 70 23 00} (length 0xb) // } // id: intptr = 0x0 (8 bytes) // flags: open_flags = 0x2 (8 bytes) // ] // returns fd_loop NONFAILING(memcpy((void*)0x200000000300, "/dev/loop#\000", 11)); res = -1; NONFAILING( res = syz_open_dev(/*dev=*/0x200000000300, /*id=*/0, /*flags=O_RDWR*/ 2)); if (res != -1) r[1] = res; // ioctl$LOOP_SET_FD arguments: [ // fd: fd_loop (resource) // cmd: const = 0x4c00 (4 bytes) // arg: fd (resource) // ] syscall(__NR_ioctl, /*fd=*/r[1], /*cmd=*/0x4c00, /*arg=*/r[0]); // mkdirat arguments: [ // fd: fd_dir (resource) // path: ptr[in, buffer] { // buffer: {2e 2f 73 79 73 00} (length 0x6) // } // mode: open_mode = 0x1ff (8 bytes) // ] NONFAILING(memcpy((void*)0x200000000400, "./sys\000", 6)); syscall( __NR_mkdirat, /*fd=*/0xffffff9c, /*path=*/0x200000000400ul, /*mode=S_IXOTH|S_IWOTH|S_IROTH|S_IXGRP|S_IWGRP|S_IRGRP|S_IXUSR|S_IWUSR|0x100*/ 0x1fful); // mount arguments: [ // src: nil // dst: ptr[in, buffer] { // buffer: {2e 2f 73 79 73 00} (length 0x6) // } // type: ptr[in, buffer] { // buffer: {73 79 73 66 73 00} (length 0x6) // } // flags: mount_flags = 0x0 (8 bytes) // data: nil // ] NONFAILING(memcpy((void*)0x200000000400, "./sys\000", 6)); NONFAILING(memcpy((void*)0x200000000500, "sysfs\000", 6)); syscall(__NR_mount, /*src=*/0ul, /*dst=*/0x200000000400ul, /*type=*/0x200000000500ul, /*flags=*/0ul, /*data=*/0ul); // openat arguments: [ // fd: fd_dir (resource) // file: ptr[in, buffer] { // buffer: {2e 2f 73 79 73 2f 6d 6f 64 75 6c 65 2f 62 6c 6f 63 6b 32 6d // 74 64 2f 70 61 72 61 6d 65 74 65 72 73 2f 62 6c 6f 63 6b 32 6d 74 64 // 00} (length 0x2c) // } // flags: open_flags = 0x1 (4 bytes) // mode: open_mode = 0x0 (2 bytes) // ] // returns fd NONFAILING(memcpy((void*)0x200000000600, "./sys/module/block2mtd/parameters/block2mtd\000", 44)); res = syscall(__NR_openat, /*fd=*/0xffffff9c, /*file=*/0x200000000600ul, /*flags=O_WRONLY*/ 1, /*mode=*/0); if (res != -1) r[2] = res; // write arguments: [ // fd: fd (resource) // buf: ptr[in, buffer] { // buffer: {2f 64 65 76 2f 6c 6f 6f 70 30 2c 36 35} (length 0xd) // } // count: len = 0xd (8 bytes) // ] NONFAILING(memcpy((void*)0x200000000700, "/dev/loop0,65", 13)); syscall(__NR_write, /*fd=*/r[2], /*buf=*/0x200000000700ul, /*count=*/0xdul); return 0; }