// https://syzkaller.appspot.com/bug?id=408ae7c8a4162a0cc35da0b0a6d252851c487a7e // 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 #include #include #include #include #include #include #include #include #include #include #include #ifndef __NR_bpf #define __NR_bpf 321 #endif 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; } #define MAX_FDS 30 #define XT_TABLE_SIZE 1536 #define XT_MAX_ENTRIES 10 struct xt_counters { uint64_t pcnt, bcnt; }; struct ipt_getinfo { char name[32]; unsigned int valid_hooks; unsigned int hook_entry[5]; unsigned int underflow[5]; unsigned int num_entries; unsigned int size; }; struct ipt_get_entries { char name[32]; unsigned int size; uint64_t entrytable[XT_TABLE_SIZE / sizeof(uint64_t)]; }; struct ipt_replace { char name[32]; unsigned int valid_hooks; unsigned int num_entries; unsigned int size; unsigned int hook_entry[5]; unsigned int underflow[5]; unsigned int num_counters; struct xt_counters* counters; uint64_t entrytable[XT_TABLE_SIZE / sizeof(uint64_t)]; }; struct ipt_table_desc { const char* name; struct ipt_getinfo info; struct ipt_replace replace; }; static struct ipt_table_desc ipv4_tables[] = { {.name = "filter"}, {.name = "nat"}, {.name = "mangle"}, {.name = "raw"}, {.name = "security"}, }; static struct ipt_table_desc ipv6_tables[] = { {.name = "filter"}, {.name = "nat"}, {.name = "mangle"}, {.name = "raw"}, {.name = "security"}, }; #define IPT_BASE_CTL 64 #define IPT_SO_SET_REPLACE (IPT_BASE_CTL) #define IPT_SO_GET_INFO (IPT_BASE_CTL) #define IPT_SO_GET_ENTRIES (IPT_BASE_CTL + 1) struct arpt_getinfo { char name[32]; unsigned int valid_hooks; unsigned int hook_entry[3]; unsigned int underflow[3]; unsigned int num_entries; unsigned int size; }; struct arpt_get_entries { char name[32]; unsigned int size; uint64_t entrytable[XT_TABLE_SIZE / sizeof(uint64_t)]; }; struct arpt_replace { char name[32]; unsigned int valid_hooks; unsigned int num_entries; unsigned int size; unsigned int hook_entry[3]; unsigned int underflow[3]; unsigned int num_counters; struct xt_counters* counters; uint64_t entrytable[XT_TABLE_SIZE / sizeof(uint64_t)]; }; struct arpt_table_desc { const char* name; struct arpt_getinfo info; struct arpt_replace replace; }; static struct arpt_table_desc arpt_tables[] = { {.name = "filter"}, }; #define ARPT_BASE_CTL 96 #define ARPT_SO_SET_REPLACE (ARPT_BASE_CTL) #define ARPT_SO_GET_INFO (ARPT_BASE_CTL) #define ARPT_SO_GET_ENTRIES (ARPT_BASE_CTL + 1) static void checkpoint_iptables(struct ipt_table_desc* tables, int num_tables, int family, int level) { int fd = socket(family, SOCK_STREAM, IPPROTO_TCP); if (fd == -1) { switch (errno) { case EAFNOSUPPORT: case ENOPROTOOPT: case ENOENT: return; } exit(1); } for (int i = 0; i < num_tables; i++) { struct ipt_table_desc* table = &tables[i]; strcpy(table->info.name, table->name); strcpy(table->replace.name, table->name); socklen_t optlen = sizeof(table->info); if (getsockopt(fd, level, IPT_SO_GET_INFO, &table->info, &optlen)) { switch (errno) { case EPERM: case ENOENT: case ENOPROTOOPT: continue; } exit(1); } if (table->info.size > sizeof(table->replace.entrytable)) exit(1); if (table->info.num_entries > XT_MAX_ENTRIES) exit(1); struct ipt_get_entries entries; memset(&entries, 0, sizeof(entries)); strcpy(entries.name, table->name); entries.size = table->info.size; optlen = sizeof(entries) - sizeof(entries.entrytable) + table->info.size; if (getsockopt(fd, level, IPT_SO_GET_ENTRIES, &entries, &optlen)) exit(1); table->replace.valid_hooks = table->info.valid_hooks; table->replace.num_entries = table->info.num_entries; table->replace.size = table->info.size; memcpy(table->replace.hook_entry, table->info.hook_entry, sizeof(table->replace.hook_entry)); memcpy(table->replace.underflow, table->info.underflow, sizeof(table->replace.underflow)); memcpy(table->replace.entrytable, entries.entrytable, table->info.size); } close(fd); } static void reset_iptables(struct ipt_table_desc* tables, int num_tables, int family, int level) { int fd = socket(family, SOCK_STREAM, IPPROTO_TCP); if (fd == -1) { switch (errno) { case EAFNOSUPPORT: case ENOPROTOOPT: case ENOENT: return; } exit(1); } for (int i = 0; i < num_tables; i++) { struct ipt_table_desc* table = &tables[i]; if (table->info.valid_hooks == 0) continue; struct ipt_getinfo info; memset(&info, 0, sizeof(info)); strcpy(info.name, table->name); socklen_t optlen = sizeof(info); if (getsockopt(fd, level, IPT_SO_GET_INFO, &info, &optlen)) exit(1); if (memcmp(&table->info, &info, sizeof(table->info)) == 0) { struct ipt_get_entries entries; memset(&entries, 0, sizeof(entries)); strcpy(entries.name, table->name); entries.size = table->info.size; optlen = sizeof(entries) - sizeof(entries.entrytable) + entries.size; if (getsockopt(fd, level, IPT_SO_GET_ENTRIES, &entries, &optlen)) exit(1); if (memcmp(table->replace.entrytable, entries.entrytable, table->info.size) == 0) continue; } struct xt_counters counters[XT_MAX_ENTRIES]; table->replace.num_counters = info.num_entries; table->replace.counters = counters; optlen = sizeof(table->replace) - sizeof(table->replace.entrytable) + table->replace.size; if (setsockopt(fd, level, IPT_SO_SET_REPLACE, &table->replace, optlen)) exit(1); } close(fd); } static void checkpoint_arptables(void) { int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd == -1) { switch (errno) { case EAFNOSUPPORT: case ENOPROTOOPT: case ENOENT: return; } exit(1); } for (unsigned i = 0; i < sizeof(arpt_tables) / sizeof(arpt_tables[0]); i++) { struct arpt_table_desc* table = &arpt_tables[i]; strcpy(table->info.name, table->name); strcpy(table->replace.name, table->name); socklen_t optlen = sizeof(table->info); if (getsockopt(fd, SOL_IP, ARPT_SO_GET_INFO, &table->info, &optlen)) { switch (errno) { case EPERM: case ENOENT: case ENOPROTOOPT: continue; } exit(1); } if (table->info.size > sizeof(table->replace.entrytable)) exit(1); if (table->info.num_entries > XT_MAX_ENTRIES) exit(1); struct arpt_get_entries entries; memset(&entries, 0, sizeof(entries)); strcpy(entries.name, table->name); entries.size = table->info.size; optlen = sizeof(entries) - sizeof(entries.entrytable) + table->info.size; if (getsockopt(fd, SOL_IP, ARPT_SO_GET_ENTRIES, &entries, &optlen)) exit(1); table->replace.valid_hooks = table->info.valid_hooks; table->replace.num_entries = table->info.num_entries; table->replace.size = table->info.size; memcpy(table->replace.hook_entry, table->info.hook_entry, sizeof(table->replace.hook_entry)); memcpy(table->replace.underflow, table->info.underflow, sizeof(table->replace.underflow)); memcpy(table->replace.entrytable, entries.entrytable, table->info.size); } close(fd); } static void reset_arptables() { int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd == -1) { switch (errno) { case EAFNOSUPPORT: case ENOPROTOOPT: case ENOENT: return; } exit(1); } for (unsigned i = 0; i < sizeof(arpt_tables) / sizeof(arpt_tables[0]); i++) { struct arpt_table_desc* table = &arpt_tables[i]; if (table->info.valid_hooks == 0) continue; struct arpt_getinfo info; memset(&info, 0, sizeof(info)); strcpy(info.name, table->name); socklen_t optlen = sizeof(info); if (getsockopt(fd, SOL_IP, ARPT_SO_GET_INFO, &info, &optlen)) exit(1); if (memcmp(&table->info, &info, sizeof(table->info)) == 0) { struct arpt_get_entries entries; memset(&entries, 0, sizeof(entries)); strcpy(entries.name, table->name); entries.size = table->info.size; optlen = sizeof(entries) - sizeof(entries.entrytable) + entries.size; if (getsockopt(fd, SOL_IP, ARPT_SO_GET_ENTRIES, &entries, &optlen)) exit(1); if (memcmp(table->replace.entrytable, entries.entrytable, table->info.size) == 0) continue; } else { } struct xt_counters counters[XT_MAX_ENTRIES]; table->replace.num_counters = info.num_entries; table->replace.counters = counters; optlen = sizeof(table->replace) - sizeof(table->replace.entrytable) + table->replace.size; if (setsockopt(fd, SOL_IP, ARPT_SO_SET_REPLACE, &table->replace, optlen)) exit(1); } close(fd); } #define NF_BR_NUMHOOKS 6 #define EBT_TABLE_MAXNAMELEN 32 #define EBT_CHAIN_MAXNAMELEN 32 #define EBT_BASE_CTL 128 #define EBT_SO_SET_ENTRIES (EBT_BASE_CTL) #define EBT_SO_GET_INFO (EBT_BASE_CTL) #define EBT_SO_GET_ENTRIES (EBT_SO_GET_INFO + 1) #define EBT_SO_GET_INIT_INFO (EBT_SO_GET_ENTRIES + 1) #define EBT_SO_GET_INIT_ENTRIES (EBT_SO_GET_INIT_INFO + 1) struct ebt_replace { char name[EBT_TABLE_MAXNAMELEN]; unsigned int valid_hooks; unsigned int nentries; unsigned int entries_size; struct ebt_entries* hook_entry[NF_BR_NUMHOOKS]; unsigned int num_counters; struct ebt_counter* counters; char* entries; }; struct ebt_entries { unsigned int distinguisher; char name[EBT_CHAIN_MAXNAMELEN]; unsigned int counter_offset; int policy; unsigned int nentries; char data[0] __attribute__((aligned(__alignof__(struct ebt_replace)))); }; struct ebt_table_desc { const char* name; struct ebt_replace replace; char entrytable[XT_TABLE_SIZE]; }; static struct ebt_table_desc ebt_tables[] = { {.name = "filter"}, {.name = "nat"}, {.name = "broute"}, }; static void checkpoint_ebtables(void) { int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd == -1) { switch (errno) { case EAFNOSUPPORT: case ENOPROTOOPT: case ENOENT: return; } exit(1); } for (size_t i = 0; i < sizeof(ebt_tables) / sizeof(ebt_tables[0]); i++) { struct ebt_table_desc* table = &ebt_tables[i]; strcpy(table->replace.name, table->name); socklen_t optlen = sizeof(table->replace); if (getsockopt(fd, SOL_IP, EBT_SO_GET_INIT_INFO, &table->replace, &optlen)) { switch (errno) { case EPERM: case ENOENT: case ENOPROTOOPT: continue; } exit(1); } if (table->replace.entries_size > sizeof(table->entrytable)) exit(1); table->replace.num_counters = 0; table->replace.entries = table->entrytable; optlen = sizeof(table->replace) + table->replace.entries_size; if (getsockopt(fd, SOL_IP, EBT_SO_GET_INIT_ENTRIES, &table->replace, &optlen)) exit(1); } close(fd); } static void reset_ebtables() { int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (fd == -1) { switch (errno) { case EAFNOSUPPORT: case ENOPROTOOPT: case ENOENT: return; } exit(1); } for (unsigned i = 0; i < sizeof(ebt_tables) / sizeof(ebt_tables[0]); i++) { struct ebt_table_desc* table = &ebt_tables[i]; if (table->replace.valid_hooks == 0) continue; struct ebt_replace replace; memset(&replace, 0, sizeof(replace)); strcpy(replace.name, table->name); socklen_t optlen = sizeof(replace); if (getsockopt(fd, SOL_IP, EBT_SO_GET_INFO, &replace, &optlen)) exit(1); replace.num_counters = 0; table->replace.entries = 0; for (unsigned h = 0; h < NF_BR_NUMHOOKS; h++) table->replace.hook_entry[h] = 0; if (memcmp(&table->replace, &replace, sizeof(table->replace)) == 0) { char entrytable[XT_TABLE_SIZE]; memset(&entrytable, 0, sizeof(entrytable)); replace.entries = entrytable; optlen = sizeof(replace) + replace.entries_size; if (getsockopt(fd, SOL_IP, EBT_SO_GET_ENTRIES, &replace, &optlen)) exit(1); if (memcmp(table->entrytable, entrytable, replace.entries_size) == 0) continue; } for (unsigned j = 0, h = 0; h < NF_BR_NUMHOOKS; h++) { if (table->replace.valid_hooks & (1 << h)) { table->replace.hook_entry[h] = (struct ebt_entries*)table->entrytable + j; j++; } } table->replace.entries = table->entrytable; optlen = sizeof(table->replace) + table->replace.entries_size; if (setsockopt(fd, SOL_IP, EBT_SO_SET_ENTRIES, &table->replace, optlen)) exit(1); } close(fd); } static void checkpoint_net_namespace(void) { checkpoint_ebtables(); checkpoint_arptables(); checkpoint_iptables(ipv4_tables, sizeof(ipv4_tables) / sizeof(ipv4_tables[0]), AF_INET, SOL_IP); checkpoint_iptables(ipv6_tables, sizeof(ipv6_tables) / sizeof(ipv6_tables[0]), AF_INET6, SOL_IPV6); } static void reset_net_namespace(void) { reset_ebtables(); reset_arptables(); reset_iptables(ipv4_tables, sizeof(ipv4_tables) / sizeof(ipv4_tables[0]), AF_INET, SOL_IP); reset_iptables(ipv6_tables, sizeof(ipv6_tables) / sizeof(ipv6_tables[0]), AF_INET6, SOL_IPV6); } static void setup_common() { if (mount(0, "/sys/fs/fuse/connections", "fusectl", 0, 0)) { } } static void setup_binderfs() { if (mkdir("/dev/binderfs", 0777)) { } if (mount("binder", "/dev/binderfs", "binder", 0, NULL)) { } if (symlink("/dev/binderfs", "./binderfs")) { } } static void loop(); static void sandbox_common() { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setsid(); struct rlimit rlim; rlim.rlim_cur = rlim.rlim_max = (200 << 20); setrlimit(RLIMIT_AS, &rlim); rlim.rlim_cur = rlim.rlim_max = 32 << 20; setrlimit(RLIMIT_MEMLOCK, &rlim); rlim.rlim_cur = rlim.rlim_max = 136 << 20; setrlimit(RLIMIT_FSIZE, &rlim); rlim.rlim_cur = rlim.rlim_max = 1 << 20; setrlimit(RLIMIT_STACK, &rlim); rlim.rlim_cur = rlim.rlim_max = 128 << 20; setrlimit(RLIMIT_CORE, &rlim); rlim.rlim_cur = rlim.rlim_max = 256; setrlimit(RLIMIT_NOFILE, &rlim); if (unshare(CLONE_NEWNS)) { } if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) { } if (unshare(CLONE_NEWIPC)) { } if (unshare(0x02000000)) { } if (unshare(CLONE_NEWUTS)) { } if (unshare(CLONE_SYSVSEM)) { } typedef struct { const char* name; const char* value; } sysctl_t; static const sysctl_t sysctls[] = { {"/proc/sys/kernel/shmmax", "16777216"}, {"/proc/sys/kernel/shmall", "536870912"}, {"/proc/sys/kernel/shmmni", "1024"}, {"/proc/sys/kernel/msgmax", "8192"}, {"/proc/sys/kernel/msgmni", "1024"}, {"/proc/sys/kernel/msgmnb", "1024"}, {"/proc/sys/kernel/sem", "1024 1048576 500 1024"}, }; unsigned i; for (i = 0; i < sizeof(sysctls) / sizeof(sysctls[0]); i++) write_file(sysctls[i].name, sysctls[i].value); } static int wait_for_loop(int pid) { if (pid < 0) exit(1); int status = 0; while (waitpid(-1, &status, __WALL) != pid) { } return WEXITSTATUS(status); } static void drop_caps(void) { struct __user_cap_header_struct cap_hdr = {}; struct __user_cap_data_struct cap_data[2] = {}; cap_hdr.version = _LINUX_CAPABILITY_VERSION_3; cap_hdr.pid = getpid(); if (syscall(SYS_capget, &cap_hdr, &cap_data)) exit(1); const int drop = (1 << CAP_SYS_PTRACE) | (1 << CAP_SYS_NICE); cap_data[0].effective &= ~drop; cap_data[0].permitted &= ~drop; cap_data[0].inheritable &= ~drop; if (syscall(SYS_capset, &cap_hdr, &cap_data)) exit(1); } static int do_sandbox_none(void) { if (unshare(CLONE_NEWPID)) { } int pid = fork(); if (pid != 0) return wait_for_loop(pid); setup_common(); sandbox_common(); drop_caps(); if (unshare(CLONE_NEWNET)) { } write_file("/proc/sys/net/ipv4/ping_group_range", "0 65535"); setup_binderfs(); loop(); 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_loop() { checkpoint_net_namespace(); } static void reset_loop() { reset_net_namespace(); } static void setup_test() { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setpgrp(); write_file("/proc/self/oom_score_adj", "1000"); } static void close_fds() { for (int fd = 3; fd < MAX_FDS; fd++) close(fd); } static void setup_binfmt_misc() { if (mount(0, "/proc/sys/fs/binfmt_misc", "binfmt_misc", 0, 0)) { } write_file("/proc/sys/fs/binfmt_misc/register", ":syz0:M:0:\x01::./file0:"); write_file("/proc/sys/fs/binfmt_misc/register", ":syz1:M:1:\x02::./file0:POC"); } static void setup_usb() { if (chmod("/dev/raw-gadget", 0666)) exit(1); } static void execute_one(void); #define WAIT_FLAGS __WALL static void loop(void) { setup_loop(); int iter = 0; for (;; iter++) { reset_loop(); int pid = fork(); if (pid < 0) exit(1); if (pid == 0) { setup_test(); execute_one(); close_fds(); 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[3] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff}; void execute_one(void) { intptr_t res = 0; *(uint32_t*)0x20000340 = 2; *(uint32_t*)0x20000344 = 4; *(uint32_t*)0x20000348 = 8; *(uint32_t*)0x2000034c = 1; *(uint32_t*)0x20000350 = 0x80; *(uint32_t*)0x20000354 = -1; *(uint32_t*)0x20000358 = 0; memset((void*)0x2000035c, 0, 16); *(uint32_t*)0x2000036c = 0; *(uint32_t*)0x20000370 = -1; *(uint32_t*)0x20000374 = 0; *(uint32_t*)0x20000378 = 0; *(uint32_t*)0x2000037c = 0; *(uint64_t*)0x20000380 = 0; res = syscall(__NR_bpf, /*cmd=*/0ul, /*arg=*/0x20000340ul, /*size=*/0x48ul); if (res != -1) r[0] = res; *(uint32_t*)0x20000480 = r[0]; syscall(__NR_bpf, /*cmd=*/0x16ul, /*arg=*/0x20000480ul, /*size=*/4ul); *(uint32_t*)0x200004c0 = 0x11; *(uint32_t*)0x200004c4 = 0x18; *(uint64_t*)0x200004c8 = 0x200001c0; memcpy((void*)0x200001c0, "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb7" "\x08\x00\x00\x00\x00\x00\x00\x7b\x8a\xf8\xff\x00\x00\x00\x00\xb7\x08" "\x00\x00\x00\x00\x00\x00\x7b\x8a\xf0\xff\x00\x00\x00\x00\xbf\xa1\x00" "\x00\x00\x00\x00\x00\x07\x01\x00\x00\xf8\xff\xff\xff\xbf\xa4\x00\x00" "\x00\x00\x00\x00\x07\x04\x00\x00\xf0\xff\xff\xff\xb7\x02\x00\x00\x00" "\x00\x00\x00\x18\x23\x00\x00", 92); *(uint32_t*)0x2000021c = r[0]; memcpy( (void*)0x20000220, "\x00\x00\x00\x00\x00\x00\x00\x00\xb7\x05\x00\x00\x00\x00\x00\x00\x85\x00" "\x00\x00\xa5\x00\x00\x00\x18\x01\x00\x00\x20\x20\x64\x05\x00\x00\x00\x00" "\x00\x20\x20\x20\x7b\x1a\xf8\xff\x00\x00\x00\x00\xbf\xa1\x00\x00\x00\x00" "\x00\x00\x07\x01\x00\x00\xf8\xff\xff\xff\xb7\x02\x00\x00\x08\x00\x00\x00" "\xb7\x03\x00\x00\x00\x00\x00\x00\xa5\x00\x00\x00\x08\x00\x00\x00\x95", 89); *(uint64_t*)0x200004d0 = 0x20000600; memcpy((void*)0x20000600, "GPL\000", 4); *(uint32_t*)0x200004d8 = 0; *(uint32_t*)0x200004dc = 0; *(uint64_t*)0x200004e0 = 0; *(uint32_t*)0x200004e8 = 0; *(uint32_t*)0x200004ec = 0; memset((void*)0x200004f0, 0, 16); *(uint32_t*)0x20000500 = 0; *(uint32_t*)0x20000504 = 0; *(uint32_t*)0x20000508 = -1; *(uint32_t*)0x2000050c = 0; *(uint64_t*)0x20000510 = 0; *(uint32_t*)0x20000518 = 0; *(uint32_t*)0x2000051c = 0; *(uint64_t*)0x20000520 = 0; *(uint32_t*)0x20000528 = 0; *(uint32_t*)0x2000052c = 0; *(uint32_t*)0x20000530 = 0; *(uint32_t*)0x20000534 = 0; *(uint64_t*)0x20000538 = 0; *(uint64_t*)0x20000540 = 0; *(uint32_t*)0x20000548 = 0; *(uint32_t*)0x2000054c = 0; res = syscall(__NR_bpf, /*cmd=*/5ul, /*arg=*/0x200004c0ul, /*size=*/0x90ul); if (res != -1) r[1] = res; *(uint64_t*)0x200001c0 = 0x20000440; memcpy((void*)0x20000440, "kfree\000", 6); *(uint32_t*)0x200001c8 = r[1]; syscall(__NR_bpf, /*cmd=*/0x11ul, /*arg=*/0x200001c0ul, /*size=*/0x10ul); *(uint32_t*)0x20000000 = 1; *(uint32_t*)0x20000004 = 8; *(uint64_t*)0x20000008 = 0x20002200; memcpy( (void*)0x20002200, "\x7a\x0a\xf8\xff\x75\x25\x73\x7c\xbf\xa1\x00\x00\x00\x00\x00\x00\x07\x01" "\x00\x00\xf8\xff\xff\xff\xb7\x02\x00\x00\x05\x00\x00\x00\xbf\x13\x00\x00" "\x00\x00\x00\x00\x85\x00\x00\x00\x06\x00\x00\x00\xb7\x00\x00\x00\x00\x00" "\x00\x00\x95\x00\x00\xf7\x00\x00\x00\x00\xb2\x59\x52\x85\xfa\x97\xea\xd0" "\x16\x91\x91\xd5\x4f\x81\x96\x21\x7f\xc5\x63\xe2\xfc\x91\xf6\xda\x4d\xad" "\x4f\x00\x78\xb1\xb5\x95\x6f\xc4\xa3\xf6\x11\xa7\xc8\x00\x00\x04\x00\x00" "\x00\x00\x00\xb1\xa2\x97\xcf\xdd\xd7\x3f\x30\xf2\x38\x2f\x6c\x2d\x3f\xfd" "\xd4\x5b\xe5\x83\x82\x3c\x0f\x09\x22\x48\xa5\x7d\x48\x62\x1f\x3c\x1c\x65" "\xee\x19\xee\x87\x5d\xaf\x45\x03\x00\x00\x00\xa5\xe1\x5b\x2f\x96\x18\xd5" "\x47\x24\x4a\x22\x00\x00\x00\x00\x08\x00\xdb\x58\x36\x20\xce\x72\x43\xd1" "\xae\xbd\xb6\x38\xd9\x1d\xbe\xf6\x61\x93\x58\x39\x9a\xa9\xc2\xac\xd0\x68" "\xc0\x3e\xfe\xfd\x8b\xc7\x7e\xdf\x2d\x34\xb1\x2c\xd4\x8a\x1b\x20\xfb\x7d" "\xd8\x43\x26\x7e\x03\x31\x75\x9f\x4e\xc6\xb5\xb0\xaf\x58\xe6\x04\xf4\x94" "\xef\xf2\x89\x02\x6d\x50\x45\xef\x08\x00\x00\x00\x00\x00\x00\x00\x77\x18" "\xa0\x9f\x48\x86\xaf\xc2\x6a\xbb\xa3\x46\x35\xd0\xe8\xb5\x98\xa5\x1b\xc7" "\x42\x13\x5a\x6e\x1d\x33\xfe\x22\x6c\x94\x4b\xc7\x0b\xb3\x0d\x43\x5a\xa8" "\xb5\x20\x2d\xb7\x61\x01\x4b\x1b\x99\x9a\x12\xdf\x6b\xee\x43\x1a\x66\x81" "\x00\x00\x00\x26\x3b\x62\x33\xe1\xc0\xfe\x30\xe3\x84\xc3\xcb\x07\xb7\x4a" "\x72\x29\x1a\x1a\x2b\x52\x3d\xd8\x1b\x66\x51\xb1\xee\x48\xe9\x99\xbb\x00" "\x48\x23\xeb\xcd\x8c\x65\x74\x3f\x31\xf8\x4b\x26\x3a\xb9\xb3\x42\x66\x92" "\xd0\x1a\xd1\x94\xf3\x02\xd7\xa6\x58\xe9\x00\x00\x00\x00\x01\x00\x00\x00" "\xb6\xb2\xf2\x5d\xdb\x8c\x64\x0a\xb3\x21\xa4\x02\x05\x8c\x92\xcd\xfb\xea" "\x88\x2b\x0b\x18\x91\xac\x21\xb6\x87\x08\x14\xcf\x4e\xe2\x3d\xdb\x79\xff" "\xf5\xeb\x15\x6e\x0a\x00\x00\x00\x00\x00\x00\xf2\xbd\x16\x4a\x17\x8d\x86" "\xd6\x93\x5e\xb8\xb7\x5b\xc4\xeb\x68\x0d\x10\xe8\xb6\xa5\x4c\x6c\x86\x74" "\xca\xf6\x3f\xf7\x66\x22\x93\x9a\x20\xd4\xaa\xdf\x85\xdb\x40\x17\x9c\x2c" "\xf8\x3e\xe0\x7e\x30\xa2\x79\xd8\xf9\xf3\xbc\x28\x2d\xeb\x43\xa0\x34\x09" "\xf8\xe6\x97\x2f\x3f\x72\x0d\x04\x59\x23\x70\x2c\xed\xe0\xf3\xe9\x14\x11" "\xf3\xf1\xb1\x6f\x06\x56\x24\xf2\x80\xa7\xdc\xce\x8d\xb9\x10\xf9\x3c\x49" "\xb9\xe0\xaa\x39\x0d\x0d\xa6\x97\x2e\xd7\x19\xd7\xe0\xef\xb2\xbb\x71\x3d" "\x18\x90\xe3\x17\xc8\xde\x10\x5c\x39\x33\xfd\x5d\x5b\xf3\x8f\x6b\x9f\xc3" "\x9f\xc8\x29\xdc\xfe\x4a\xf8\xac\x5f\xbb\x73\x14\xa7\xa4\x33\xe0\x18\x27" "\x67\xd1\x37\x6e\xda\x2b\x9c\x66\x20\x03\x49\xe6\x2d\x4d\x0a\xb1\xa1\xdc" "\x51\x90\x7c\x98\x00\x00\x00\x00\xa8\x57\xd6\x1b\x0d\x66\xc3\xf6\xda\x8a" "\xed\x31\x02\x7c\x33\x20\x4e\xa0\xfa\x06\x20\x11\x19\x20\xd3\xf2\x49\x80" "\xe9\x99\x5a\x51\x0b\xd8\x7b\x06\x44\x0a\x0a\x26\x13\x00\x98\xb9\x01\xc5" "\x3a\x02\xcf\xbf\xd8\xbc\xbd\xec\x9f\x34\x54\x2c\x3c\x96\x52\xad\xef\xde" "\x55\x5e\xcd\x28\xeb\xc8\x80\x82\xba\xb4\x31\xee\x3e\x1a\xdb\x5b\x0a\xd1" "\x4c\x79\xdd\x44\x11\xec\xc9\x6c\x51\x2f\x3b\x72\xa9\xb3\xa0\xc3\xe0\x7e" "\xc6\xb4\x27\xbd\xc0\xbf\x39\x63\xe9\xf8\x02\xa5\xfe\xab\x82\xa9\x89\xdb" "\x62\xd8\xd1\x33\x9f\x84\x2b\x3f\x59\x3d\x6c\x24\xfe\x01\x5e\xc6\x3c\x65" "\x8b\xa7\xc4\xfa\xe1\x75\x14\xf8\x02\x70\x9a\xb4\xfa\x5c\xaa\x93\x2d\x4b" "\x65\xa5\xec\xfc\x42\x28\x99\x51\x3d\xdd\xe6\xec\x04\x97\x4f\x99\x81\xa8" "\xc1\x55\x00\x00\x00\x00\x00\x00\x00\x00\x97\xd6\xe0\x11\x73\x31\x28\xcb" "\x37\xb1\xce\xd7\x85\xe4\x72\x68\x23\xe5\xa4\x6e\x87\x60\x08\x6c\x63\x9b" "\x8d\xc9\xb0\xcb\x5f\xa8\x3a\x7f\x75\x4d\xfc\x5e\xaf\xdc\xc8\x2d\x29\x84" "\x3c\x75\x33\x81\xf7\x52\x6c\x9a\xe5\x30\x52\xa2\x27\x47\x8c\xa5\x7f\x06" "\x0d\x57\x3b\x92\x25\xe1\x46\x38\x69\x9c\x7c\xfa\xdb\xd7\x8a\x90\xde\x75" "\x2a\xb7\xd5\x40\xe1\x78\xfe\xff\x2c\xac\x75\x73\xc4\x35\xf7\x19\xb3\x4a" "\xbe\x5a\x5d\x70\xc2\xd7\xbc\xf7\xde\xf2\x5c\xa9\x9c\x15\x53\xac\x8a\xcc" "\x6e\x6d\x54\xaa\x69\x7d\xa5\xc5\xf5\x93\x06\x67\xb4\x52\x53\x15\x31\xad" "\x31\x88\xcb\xd2\x0e\x3a\x7b\xaf\x1f\x71\x18\x76\x53\xc8\x8e\x7f\xba\x2b" "\x81\xb9\x59\x66\x70\x49\xcc\x52\x04\x7c\x27\xef\xac\x9a\x88\xa8\x17\xf0" "\xfc\x21\x0a\x52\x06\x0e\x61\xad\x2f\xed\xce\x1b\x11\xf6\xeb\xfc\x22\x2d" "\xe9\x66\xaa\x4c\x1d\xfb\x67\xe2\x88\x41\x4c\xb5\x3c\x4a\xa3\x01\x77\x5f" "\xeb\xef\x9e\xe0\x35\x61\x8b\x52\xb2\xae\x7a\xd0\xfd\x32\x23\xd4\x81\x10" "\x62\x72\xd8\x84\x99\x37\xe4\x64\x20\xab\x38\x33\x2c\x5c\x18\xe5\x6d\x91" "\x00\x00\x00\x00\x00\x00\x00", 1033); *(uint64_t*)0x20000010 = 0x20000100; memcpy((void*)0x20000100, "GPL\000", 4); *(uint32_t*)0x20000018 = 0; *(uint32_t*)0x2000001c = 0; *(uint64_t*)0x20000020 = 0; *(uint32_t*)0x20000028 = 0; *(uint32_t*)0x2000002c = 0; memset((void*)0x20000030, 0, 16); *(uint32_t*)0x20000040 = 0; *(uint32_t*)0x20000044 = 0; *(uint32_t*)0x20000048 = -1; *(uint32_t*)0x2000004c = 8; *(uint64_t*)0x20000050 = 0; *(uint32_t*)0x20000058 = 0; *(uint32_t*)0x2000005c = 0x10; *(uint64_t*)0x20000060 = 0; *(uint32_t*)0x20000068 = 0; *(uint32_t*)0x2000006c = 0; *(uint32_t*)0x20000070 = -1; *(uint32_t*)0x20000074 = 0; *(uint64_t*)0x20000078 = 0; *(uint64_t*)0x20000080 = 0; *(uint32_t*)0x20000088 = 0x10; *(uint32_t*)0x2000008c = 0; res = syscall(__NR_bpf, /*cmd=*/5ul, /*arg=*/0x20000000ul, /*size=*/0x48ul); if (res != -1) r[2] = res; *(uint32_t*)0x20000080 = r[2]; *(uint32_t*)0x20000084 = 0x2000000; *(uint32_t*)0x20000088 = 0xe; *(uint32_t*)0x2000008c = 0x55; *(uint64_t*)0x20000090 = 0x20000140; memcpy((void*)0x20000140, "\xa0\x6a\xd8\x76\xd5\x6a\x00\x64\xd0\x82\x77\x8c\x39\x38", 14); *(uint64_t*)0x20000098 = 0x20000380; *(uint32_t*)0x200000a0 = 0xa00; *(uint32_t*)0x200000a4 = 0x4000000; *(uint32_t*)0x200000a8 = 0; *(uint32_t*)0x200000ac = 0x7000000; *(uint64_t*)0x200000b0 = 0x20000000; *(uint64_t*)0x200000b8 = 0x20000000; *(uint32_t*)0x200000c0 = 0; *(uint32_t*)0x200000c4 = 0; *(uint32_t*)0x200000c8 = 0; syscall(__NR_bpf, /*cmd=*/0xaul, /*arg=*/0x20000080ul, /*size=*/0x28ul); } 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_binfmt_misc(); setup_usb(); do_sandbox_none(); return 0; }