Dear developers and maintainers, We encountered a null pointer dereference bug while using our modified syzkaller. It was tested against the upstream kernel (6.9). The kernel is compiled by clang-14, kernel config is attached to this email. Kernel crash log is listed below. ``` BUG: kernel NULL pointer dereference, address: 0000000000000010 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: Oops: 0000 [#1] PREEMPT SMP KASAN NOPTI CPU: 1 PID: 0 Comm: swapper/1 Not tainted 6.9.0-05151-g1b294a1f3561 #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 RIP: 0010:find_stack lib/stackdepot.c:553 [inline] RIP: 0010:stack_depot_save_flags+0x1a0/0x850 lib/stackdepot.c:618 Code: 48 89 54 24 18 31 f6 4c 89 44 24 10 e8 69 be c7 ff 31 f6 4c 8b 44 24 10 48 8b 54 24 18 45 85 e4 75 62 4d 8b 3f 49 39 d7 74 5d <45> 39 77 10 75 f2 45 39 47 14 75 ec 31 c0 49 8b 4c c5 00 49 3b 4c RSP: 0018:ffffc900001e7540 EFLAGS: 00010203 RAX: ffff8880bd200000 RBX: 0000000000000001 RCX: 00000000002086f0 RDX: ffff8880bd4086f0 RSI: 0000000000000000 RDI: 0000000080adfd56 RBP: 0000000000000010 R08: 0000000000000010 R09: ffffc900001e7510 R10: 0000000000000003 R11: ffffffff817b2e00 R12: 1ffff9200003ceb8 R13: ffffc900001e75e0 R14: 00000000fac2086f R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff8880be400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000010 CR3: 000000000db34000 CR4: 0000000000750ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: <IRQ> save_stack+0xf7/0x1e0 mm/page_owner.c:157 __set_page_owner+0x89/0x560 mm/page_owner.c:325 set_page_owner include/linux/page_owner.h:32 [inline] post_alloc_hook+0x1e6/0x210 mm/page_alloc.c:1534 prep_new_page mm/page_alloc.c:1541 [inline] get_page_from_freelist+0x7d2/0x850 mm/page_alloc.c:3317 __alloc_pages+0x25e/0x580 mm/page_alloc.c:4575 __alloc_pages_node include/linux/gfp.h:238 [inline] alloc_pages_node include/linux/gfp.h:261 [inline] alloc_slab_page+0x6b/0x1a0 mm/slub.c:2190 allocate_slab+0x5d/0x200 mm/slub.c:2353 new_slab mm/slub.c:2406 [inline] ___slab_alloc+0xa95/0xf20 mm/slub.c:3592 __slab_alloc mm/slub.c:3682 [inline] __slab_alloc_node mm/slub.c:3735 [inline] slab_alloc_node mm/slub.c:3908 [inline] kmem_cache_alloc_node+0x245/0x390 mm/slub.c:3961 __alloc_skb+0x19b/0x3f0 net/core/skbuff.c:656 alloc_skb include/linux/skbuff.h:1308 [inline] nlmsg_new include/net/netlink.h:1015 [inline] inet6_prefix_notify net/ipv6/addrconf.c:6229 [inline] addrconf_prefix_rcv+0x912/0x1660 net/ipv6/addrconf.c:2914 ndisc_router_discovery+0x17f8/0x38e0 net/ipv6/ndisc.c:1566 icmpv6_rcv+0x1068/0x18f0 net/ipv6/icmp.c:979 ip6_protocol_deliver_rcu+0x1064/0x1590 net/ipv6/ip6_input.c:438 ip6_input_finish+0x17d/0x2c0 net/ipv6/ip6_input.c:483 NF_HOOK include/linux/netfilter.h:314 [inline] ip6_input net/ipv6/ip6_input.c:492 [inline] ip6_mc_input+0x9b7/0xc00 net/ipv6/ip6_input.c:586 ip6_sublist_rcv_finish net/ipv6/ip6_input.c:88 [inline] ip6_list_rcv_finish net/ipv6/ip6_input.c:146 [inline] ip6_sublist_rcv+0xcb3/0xd20 net/ipv6/ip6_input.c:320 ipv6_list_rcv+0x431/0x480 net/ipv6/ip6_input.c:355 __netif_receive_skb_list_ptype net/core/dev.c:5667 [inline] __netif_receive_skb_list_core+0x76a/0x9c0 net/core/dev.c:5715 __netif_receive_skb_list+0x42d/0x4d0 net/core/dev.c:5767 netif_receive_skb_list_internal+0x5e7/0x910 net/core/dev.c:5859 gro_normal_list include/net/gro.h:515 [inline] napi_complete_done+0x30a/0x800 net/core/dev.c:6202 e1000_clean+0xf5d/0x3bc0 drivers/net/ethernet/intel/e1000/e1000_main.c:3809 __napi_poll+0xca/0x480 net/core/dev.c:6721 napi_poll net/core/dev.c:6790 [inline] net_rx_action+0x7cb/0x1000 net/core/dev.c:6906 handle_softirqs+0x274/0x730 kernel/softirq.c:554 __do_softirq kernel/softirq.c:588 [inline] invoke_softirq kernel/softirq.c:428 [inline] __irq_exit_rcu+0xd7/0x1a0 kernel/softirq.c:637 irq_exit_rcu+0x9/0x20 kernel/softirq.c:649 common_interrupt+0xaa/0xd0 arch/x86/kernel/irq.c:278 </IRQ> <TASK> asm_common_interrupt+0x26/0x40 arch/x86/include/asm/idtentry.h:693 RIP: 0010:native_irq_disable arch/x86/include/asm/irqflags.h:37 [inline] RIP: 0010:arch_local_irq_disable arch/x86/include/asm/irqflags.h:72 [inline] RIP: 0010:default_idle+0x13/0x20 arch/x86/kernel/process.c:743 Code: c0 08 00 00 00 4d 29 c8 4c 01 c7 4c 29 c2 e9 76 ff ff ff cc cc cc cc f3 0f 1e fa 66 90 0f 00 2d 13 07 39 00 f3 0f 1e fa fb f4 <fa> c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa e9 d7 ff ff ff RSP: 0018:ffffc9000017fdc8 EFLAGS: 000002c6 RAX: 9f03dcce11ef6a00 RBX: ffffffff8166d8ff RCX: 00000000000b05d1 RDX: 0000000000000001 RSI: ffffffff8b6c8be0 RDI: ffffffff8bce04a0 RBP: ffffc9000017ff20 R08: ffff8880be437d0b R09: 1ffff11017c86fa1 R10: dffffc0000000000 R11: ffffed1017c86fa2 R12: 1ffff9200002ffd2 R13: 1ffff1100c15b000 R14: 0000000000000001 R15: dffffc0000000000 default_idle_call+0x74/0xb0 kernel/sched/idle.c:117 cpuidle_idle_call kernel/sched/idle.c:191 [inline] do_idle+0x20f/0x580 kernel/sched/idle.c:332 cpu_startup_entry+0x41/0x60 kernel/sched/idle.c:430 start_secondary+0x100/0x100 arch/x86/kernel/smpboot.c:313 common_startup_64+0x13e/0x147 </TASK> Modules linked in: CR2: 0000000000000010 ---[ end trace 0000000000000000 ]--- RIP: 0010:find_stack lib/stackdepot.c:553 [inline] RIP: 0010:stack_depot_save_flags+0x1a0/0x850 lib/stackdepot.c:618 Code: 48 89 54 24 18 31 f6 4c 89 44 24 10 e8 69 be c7 ff 31 f6 4c 8b 44 24 10 48 8b 54 24 18 45 85 e4 75 62 4d 8b 3f 49 39 d7 74 5d <45> 39 77 10 75 f2 45 39 47 14 75 ec 31 c0 49 8b 4c c5 00 49 3b 4c RSP: 0018:ffffc900001e7540 EFLAGS: 00010203 RAX: ffff8880bd200000 RBX: 0000000000000001 RCX: 00000000002086f0 RDX: ffff8880bd4086f0 RSI: 0000000000000000 RDI: 0000000080adfd56 RBP: 0000000000000010 R08: 0000000000000010 R09: ffffc900001e7510 R10: 0000000000000003 R11: ffffffff817b2e00 R12: 1ffff9200003ceb8 R13: ffffc900001e75e0 R14: 00000000fac2086f R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff8880be400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000010 CR3: 000000000db34000 CR4: 0000000000750ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 ---------------- Code disassembly (best guess): 0: 48 89 54 24 18 mov %rdx,0x18(%rsp) 5: 31 f6 xor %esi,%esi 7: 4c 89 44 24 10 mov %r8,0x10(%rsp) c: e8 69 be c7 ff callq 0xffc7be7a 11: 31 f6 xor %esi,%esi 13: 4c 8b 44 24 10 mov 0x10(%rsp),%r8 18: 48 8b 54 24 18 mov 0x18(%rsp),%rdx 1d: 45 85 e4 test %r12d,%r12d 20: 75 62 jne 0x84 22: 4d 8b 3f mov (%r15),%r15 25: 49 39 d7 cmp %rdx,%r15 28: 74 5d je 0x87 * 2a: 45 39 77 10 cmp %r14d,0x10(%r15) <-- trapping instruction 2e: 75 f2 jne 0x22 30: 45 39 47 14 cmp %r8d,0x14(%r15) 34: 75 ec jne 0x22 36: 31 c0 xor %eax,%eax 38: 49 8b 4c c5 00 mov 0x0(%r13,%rax,8),%rcx 3d: 49 rex.WB 3e: 3b .byte 0x3b 3f: 4c rex.WR ``` The syz repro shows that it only consist of open to /dev/sg and an ioctl to that device: (For how to execute syz repro, please refer to introduction of syzkaller: https://github.com/google/syzkaller/blob/master/docs/executing_syzkaller_programs.md) ``` r0 = syz_open_dev$sg(&(0x7f0000004f00), 0x0, 0x0) ioctl$SCSI_IOCTL_SEND_COMMAND(r0, 0x1, &(0x7f0000000040)=ANY=[@ANYBLOB="0000000007000000850a455584e48b565869e5b0ce4925"]) ``` The C repro is listed below: ``` #define _GNU_SOURCE #include <dirent.h> #include <endian.h> #include <errno.h> #include <fcntl.h> #include <signal.h> #include <stdarg.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/prctl.h> #include <sys/stat.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/wait.h> #include <time.h> #include <unistd.h> static void sleep_ms(uint64_t ms) { usleep(ms * 1000); } static uint64_t current_time_ms(void) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts)) exit(1); return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; } 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 { char buf[1024]; char* hash; strncpy(buf, (char*)a0, sizeof(buf) - 1); buf[sizeof(buf) - 1] = 0; while ((hash = strchr(buf, '#'))) { *hash = '0' + (char)(a1 % 10); a1 /= 10; } return open(buf, a2, 0); } } static void kill_and_wait(int pid, int* status) { kill(-pid, SIGKILL); kill(pid, SIGKILL); for (int i = 0; i < 100; i++) { if (waitpid(-1, status, WNOHANG | __WALL) == pid) return; usleep(1000); } DIR* dir = opendir("/sys/fs/fuse/connections"); if (dir) { for (;;) { struct dirent* ent = readdir(dir); if (!ent) break; if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue; char abort[300]; snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", ent->d_name); int fd = open(abort, O_WRONLY); if (fd == -1) { continue; } if (write(fd, abort, 1) < 0) { } close(fd); } closedir(dir); } else { } while (waitpid(-1, status, __WALL) != pid) { } } static void setup_test() { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setpgrp(); write_file("/proc/self/oom_score_adj", "1000"); } static void setup_sysctl() { char mypid[32]; snprintf(mypid, sizeof(mypid), "%d", getpid()); 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"}, {"/proc/sys/kernel/ctrl-alt-del", "0"}, {"/proc/sys/kernel/cad_pid", mypid}, }; for (size_t i = 0; i < sizeof(files) / sizeof(files[0]); i++) { if (!write_file(files[i].name, files[i].data)) printf("write to %s failed: %s\n", files[i].name, strerror(errno)); } } static void execute_one(void); #define WAIT_FLAGS __WALL static void loop(void) { int iter = 0; for (;; iter++) { int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { setup_test(); execute_one(); exit(0); } int status = 0; uint64_t start = current_time_ms(); for (;;) { if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) break; sleep_ms(1); if (current_time_ms() - start < 5000) continue; kill_and_wait(pid, &status); break; } } } uint64_t r[1] = {0xffffffffffffffff}; void execute_one(void) { intptr_t res = 0; memcpy((void*)0x20004f00, "/dev/sg#\000", 9); res = -1; res = syz_open_dev(/*dev=*/0x20004f00, /*id=*/0, /*flags=*/0); if (res != -1) r[0] = res; memcpy((void*)0x20000040, "\x00\x00\x00\x00\x07\x00\x00\x00\x85\x0a\x45\x55\x84\xe4\x8b\x56\x58" "\x69\xe5\xb0\xce\x49\x25", 23); syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/1, /*arg=*/0x20000040ul); } int main(void) { syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1, /*offset=*/0ul); setup_sysctl(); loop(); return 0; } ``` We tested this C repro on the latest commit of the upstream kernel. It still crashed but at a different location. Here is another bug that crashes elsewhere but may have the same root cause: ``` BUG: Bad rss-counter state mm:ffff8880668dc280 type:MM_ANONPAGES val:2 BUG: non-zero pgtables_bytes on freeing mm: 4096 ------------[ cut here ]------------ WARNING: CPU: 1 PID: 8096 at include/linux/mmap_lock.h:71 mmap_assert_write_locked include/linux/mmap_lock.h:71 [inline] WARNING: CPU: 1 PID: 8096 at include/linux/mmap_lock.h:71 __is_vma_write_locked include/linux/mm.h:708 [inline] WARNING: CPU: 1 PID: 8096 at include/linux/mmap_lock.h:71 vma_start_write include/linux/mm.h:727 [inline] WARNING: CPU: 1 PID: 8096 at include/linux/mmap_lock.h:71 dup_mmap+0xf44/0x1a30 kernel/fork.c:671 Modules linked in: CPU: 1 PID: 8096 Comm: syz-executor375 Not tainted 6.9.0-05151-g1b294a1f3561 #2 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 RIP: 0010:mmap_assert_write_locked include/linux/mmap_lock.h:71 [inline] RIP: 0010:__is_vma_write_locked include/linux/mm.h:708 [inline] RIP: 0010:vma_start_write include/linux/mm.h:727 [inline] RIP: 0010:dup_mmap+0xf44/0x1a30 kernel/fork.c:671 Code: 89 f7 48 c7 c6 ff ff ff ff e8 e8 9d cf 09 48 85 c0 0f 84 e0 00 00 00 48 89 c3 e8 27 76 3b 00 e9 d5 f7 ff ff e8 1d 76 3b 00 90 <0f> 0b 90 e9 3d f8 ff ff 48 c7 c1 6c 98 4b 8f 80 e1 07 80 c1 03 38 RSP: 0018:ffffc90002a8f8c0 EFLAGS: 00010293 RAX: ffffffff815305b3 RBX: 0000000000000000 RCX: ffff88801b580000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffffc90002a8fa28 R08: ffffffff8152fde5 R09: ffffffff8b227880 R10: 0000000000000004 R11: ffff88801b580000 R12: ffff88806bf89c10 R13: 1ffff1100d7f1382 R14: 0000000000000000 R15: dffffc0000000000 FS: 000055558d7ad880(0000) GS:ffff8880be400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000020000048 CR3: 0000000068130000 CR4: 0000000000750ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: <TASK> dup_mm kernel/fork.c:1688 [inline] copy_mm+0x143/0x430 kernel/fork.c:1737 copy_process+0x1810/0x3d30 kernel/fork.c:2390 kernel_clone+0x228/0x6b0 kernel/fork.c:2797 __do_sys_clone kernel/fork.c:2940 [inline] __se_sys_clone kernel/fork.c:2924 [inline] __x64_sys_clone+0x26b/0x2e0 kernel/fork.c:2924 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xe4/0x240 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x67/0x6f RIP: 0033:0x7f5a28557e7f Code: ed 0f 85 64 01 00 00 64 4c 8b 0c 25 10 00 00 00 45 31 c0 4d 8d 91 d0 02 00 00 31 d2 31 f6 bf 11 00 20 01 b8 38 00 00 00 0f 05 <48> 3d 00 f0 ff ff 0f 87 f5 00 00 00 41 89 c5 85 c0 0f 85 fc 00 00 RSP: 002b:00007ffd62c1f6c0 EFLAGS: 00000246 ORIG_RAX: 0000000000000038 RAX: ffffffffffffffda RBX: 0000000000001fa4 RCX: 00007f5a28557e7f RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000001200011 RBP: 0000000000000000 R08: 0000000000000000 R09: 000055558d7ad880 R10: 000055558d7adb50 R11: 0000000000000246 R12: 0000000000000000 R13: 00007ffd62c1f700 R14: 0000000000000002 R15: 00007ffd62c1f720 </TASK> ``` The C repro is listed below: ``` // autogenerated by syzkaller (https://github.com/google/syzkaller) #define _GNU_SOURCE #include <dirent.h> #include <endian.h> #include <errno.h> #include <fcntl.h> #include <signal.h> #include <stdarg.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/mount.h> #include <sys/prctl.h> #include <sys/stat.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/wait.h> #include <time.h> #include <unistd.h> static void sleep_ms(uint64_t ms) { usleep(ms * 1000); } static uint64_t current_time_ms(void) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts)) exit(1); return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; } 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 { char buf[1024]; char* hash; strncpy(buf, (char*)a0, sizeof(buf) - 1); buf[sizeof(buf) - 1] = 0; while ((hash = strchr(buf, '#'))) { *hash = '0' + (char)(a1 % 10); a1 /= 10; } return open(buf, a2, 0); } } #define FS_IOC_SETFLAGS _IOW('f', 2, long) static void remove_dir(const char* dir) { int iter = 0; DIR* dp = 0; retry: while (umount2(dir, MNT_DETACH | UMOUNT_NOFOLLOW) == 0) { } dp = opendir(dir); if (dp == NULL) { if (errno == EMFILE) { exit(1); } exit(1); } struct dirent* ep = 0; while ((ep = readdir(dp))) { if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0) continue; char filename[FILENAME_MAX]; snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name); while (umount2(filename, MNT_DETACH | UMOUNT_NOFOLLOW) == 0) { } struct stat st; if (lstat(filename, &st)) exit(1); if (S_ISDIR(st.st_mode)) { remove_dir(filename); continue; } int i; for (i = 0;; i++) { if (unlink(filename) == 0) break; if (errno == EPERM) { int fd = open(filename, O_RDONLY); if (fd != -1) { long flags = 0; if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == 0) { } close(fd); continue; } } if (errno == EROFS) { break; } if (errno != EBUSY || i > 100) exit(1); if (umount2(filename, MNT_DETACH | UMOUNT_NOFOLLOW)) exit(1); } } closedir(dp); for (int i = 0;; i++) { if (rmdir(dir) == 0) break; if (i < 100) { if (errno == EPERM) { int fd = open(dir, O_RDONLY); if (fd != -1) { long flags = 0; if (ioctl(fd, FS_IOC_SETFLAGS, &flags) == 0) { } close(fd); continue; } } if (errno == EROFS) { break; } if (errno == EBUSY) { if (umount2(dir, MNT_DETACH | UMOUNT_NOFOLLOW)) exit(1); continue; } if (errno == ENOTEMPTY) { if (iter < 100) { iter++; goto retry; } } } exit(1); } } static void kill_and_wait(int pid, int* status) { kill(-pid, SIGKILL); kill(pid, SIGKILL); for (int i = 0; i < 100; i++) { if (waitpid(-1, status, WNOHANG | __WALL) == pid) return; usleep(1000); } DIR* dir = opendir("/sys/fs/fuse/connections"); if (dir) { for (;;) { struct dirent* ent = readdir(dir); if (!ent) break; if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue; char abort[300]; snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", ent->d_name); int fd = open(abort, O_WRONLY); if (fd == -1) { continue; } if (write(fd, abort, 1) < 0) { } close(fd); } closedir(dir); } else { } while (waitpid(-1, status, __WALL) != pid) { } } static void setup_test() { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setpgrp(); write_file("/proc/self/oom_score_adj", "1000"); if (symlink("/dev/binderfs", "./binderfs")) { } } static void execute_one(void); #define WAIT_FLAGS __WALL static void loop(void) { int iter = 0; for (;; iter++) { char cwdbuf[32]; sprintf(cwdbuf, "./%d", iter); if (mkdir(cwdbuf, 0777)) exit(1); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { if (chdir(cwdbuf)) exit(1); setup_test(); execute_one(); exit(0); } int status = 0; uint64_t start = current_time_ms(); for (;;) { if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) break; sleep_ms(1); if (current_time_ms() - start < 5000) continue; kill_and_wait(pid, &status); break; } remove_dir(cwdbuf); } } uint64_t r[1] = {0xffffffffffffffff}; void execute_one(void) { intptr_t res = 0; syscall(__NR_ioctl, /*fd=*/-1, /*cmd=*/0xc0c0583b, /*arg=*/0ul); memcpy((void*)0x20004f00, "/dev/sg#\000", 9); res = -1; res = syz_open_dev(/*dev=*/0x20004f00, /*id=*/0, /*flags=*/0); if (res != -1) r[0] = res; memcpy((void*)0x20000040, "\x00\x00\x00\x00\x07\x00\x00\x00\x85\x0a\x45\x55\x84\xe4\x8b\x56\x58" "\x69\xe5\xb0\xce\x49\x25", 23); syscall(__NR_ioctl, /*fd=*/r[0], /*cmd=*/1, /*arg=*/0x20000040ul); } int main(void) { syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/ 7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1, /*offset=*/0ul); syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul, /*fd=*/-1, /*offset=*/0ul); use_temporary_dir(); loop(); return 0; } ``` If you have any questions, please contact us. Reported by Yue Sun <samsun1006219@xxxxxxxxx> Reported by xingwei lee <xrivendell7@xxxxxxxxx> Best Regards, Yue
Attachment:
config
Description: Binary data