// https://syzkaller.appspot.com/bug?id=a5c74eee04149854dd8b59fdfc0529a60be422a7 // autogenerated by syzkaller (http://github.com/google/syzkaller) #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include __attribute__((noreturn)) static void doexit(int status) { volatile unsigned i; syscall(__NR_exit_group, status); for (i = 0;; i++) { } } #include #include #include #include #include #include #include const int kFailStatus = 67; const int kRetryStatus = 69; static void fail(const char* msg, ...) { int e = errno; va_list args; va_start(args, msg); vfprintf(stderr, msg, args); va_end(args); fprintf(stderr, " (errno %d)\n", e); doexit((e == ENOMEM || e == EAGAIN) ? kRetryStatus : kFailStatus); } static void use_temporary_dir() { char tmpdir_template[] = "./syzkaller.XXXXXX"; char* tmpdir = mkdtemp(tmpdir_template); if (!tmpdir) fail("failed to mkdtemp"); if (chmod(tmpdir, 0777)) fail("failed to chmod"); if (chdir(tmpdir)) fail("failed to chdir"); } static void loop(); static void sandbox_common() { prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); setpgrp(); setsid(); struct rlimit rlim; rlim.rlim_cur = rlim.rlim_max = 128 << 20; setrlimit(RLIMIT_AS, &rlim); rlim.rlim_cur = rlim.rlim_max = 8 << 20; setrlimit(RLIMIT_MEMLOCK, &rlim); rlim.rlim_cur = rlim.rlim_max = 1 << 20; setrlimit(RLIMIT_FSIZE, &rlim); rlim.rlim_cur = rlim.rlim_max = 1 << 20; setrlimit(RLIMIT_STACK, &rlim); rlim.rlim_cur = rlim.rlim_max = 0; setrlimit(RLIMIT_CORE, &rlim); unshare(CLONE_NEWNS); unshare(CLONE_NEWIPC); unshare(CLONE_IO); } 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) { close(fd); return false; } close(fd); return true; } static int real_uid; static int real_gid; __attribute__((aligned(64 << 10))) static char sandbox_stack[1 << 20]; static int namespace_sandbox_proc(void* arg) { sandbox_common(); write_file("/proc/self/setgroups", "deny"); if (!write_file("/proc/self/uid_map", "0 %d 1\n", real_uid)) fail("write of /proc/self/uid_map failed"); if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid)) fail("write of /proc/self/gid_map failed"); if (mkdir("./syz-tmp", 0777)) fail("mkdir(syz-tmp) failed"); if (mount("", "./syz-tmp", "tmpfs", 0, NULL)) fail("mount(tmpfs) failed"); if (mkdir("./syz-tmp/newroot", 0777)) fail("mkdir failed"); if (mkdir("./syz-tmp/newroot/dev", 0700)) fail("mkdir failed"); if (mount("/dev", "./syz-tmp/newroot/dev", NULL, MS_BIND | MS_REC | MS_PRIVATE, NULL)) fail("mount(dev) failed"); if (mkdir("./syz-tmp/newroot/proc", 0700)) fail("mkdir failed"); if (mount(NULL, "./syz-tmp/newroot/proc", "proc", 0, NULL)) fail("mount(proc) failed"); if (mkdir("./syz-tmp/pivot", 0777)) fail("mkdir failed"); if (syscall(SYS_pivot_root, "./syz-tmp", "./syz-tmp/pivot")) { if (chdir("./syz-tmp")) fail("chdir failed"); } else { if (chdir("/")) fail("chdir failed"); if (umount2("./pivot", MNT_DETACH)) fail("umount failed"); } if (chroot("./newroot")) fail("chroot failed"); if (chdir("/")) fail("chdir failed"); 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)) fail("capget failed"); cap_data[0].effective &= ~(1 << CAP_SYS_PTRACE); cap_data[0].permitted &= ~(1 << CAP_SYS_PTRACE); cap_data[0].inheritable &= ~(1 << CAP_SYS_PTRACE); if (syscall(SYS_capset, &cap_hdr, &cap_data)) fail("capset failed"); loop(); doexit(1); } static int do_sandbox_namespace(int executor_pid, bool enable_tun) { real_uid = getuid(); real_gid = getgid(); mprotect(sandbox_stack, 4096, PROT_NONE); return clone( namespace_sandbox_proc, &sandbox_stack[sizeof(sandbox_stack) - 64], CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNET, NULL); } long r[45]; void loop() { memset(r, -1, sizeof(r)); r[0] = syscall(__NR_mmap, 0x20000000ul, 0xfff000ul, 0x3ul, 0x32ul, 0xfffffffffffffffful, 0x0ul); r[1] = syscall(__NR_socket, 0xaul, 0x1ul, 0x0ul); *(uint64_t*)0x20000000 = (uint64_t)0x0; *(uint64_t*)0x20000008 = (uint64_t)0x2000000000; *(uint32_t*)0x20000010 = (uint32_t)0x0; *(uint32_t*)0x20000014 = (uint32_t)0x3; *(uint32_t*)0x20000018 = (uint32_t)0x1; *(uint64_t*)0x20000020 = (uint64_t)0x4; *(uint64_t*)0x20000028 = (uint64_t)0x0; *(uint64_t*)0x20000030 = (uint64_t)0x0; *(uint64_t*)0x20000038 = (uint64_t)0x0; *(uint64_t*)0x20000040 = (uint64_t)0x0; *(uint32_t*)0x20000048 = (uint32_t)0x0; *(uint32_t*)0x2000004c = (uint32_t)0x0; *(uint32_t*)0x20000050 = (uint32_t)0x0; *(uint32_t*)0x20000054 = (uint32_t)0x0; r[16] = syscall(__NR_ioctl, 0xfffffffffffffffful, 0xc020660bul, 0x20000000ul); r[17] = syscall(__NR_ioctl, r[1], 0x8918ul, 0x20000000ul); r[18] = syscall(__NR_socket, 0x11ul, 0x3ul, 0x0ul); memcpy((void*)0x20155000, "\x20\x40\x01\x6f", 4); r[20] = syscall(__NR_setsockopt, r[18], 0x107ul, 0xful, 0x20155000ul, 0x4ul); *(uint64_t*)0x209bffab = (uint64_t)0x202b0000; *(uint32_t*)0x209bffb3 = (uint32_t)0x60; *(uint64_t*)0x209bffbb = (uint64_t)0x20886fe0; *(uint64_t*)0x209bffc3 = (uint64_t)0x2; *(uint64_t*)0x209bffcb = (uint64_t)0x208adf10; *(uint64_t*)0x209bffd3 = (uint64_t)0x10; *(uint32_t*)0x209bffdb = (uint32_t)0x0; *(uint16_t*)0x202b0000 = (uint16_t)0x27; *(uint32_t*)0x202b0004 = (uint32_t)0x4; *(uint32_t*)0x202b0008 = (uint32_t)0x0; *(uint32_t*)0x202b000c = (uint32_t)0x0; *(uint8_t*)0x202b0010 = (uint8_t)0x0; *(uint8_t*)0x202b0011 = (uint8_t)0x0; memcpy((void*)0x202b0012, "\xa2\x84\x02\x7e\x94\x77\x5b\xb0\xa6\x1c\x0a\x37\xf9\x8a\x86" "\xd1\x53\x9b\xce\xf0\x5a\x11\x31\x1b\x56\xeb\x8e\x51\x3a\xfa" "\x21\x84\x79\xb8\xc5\x41\x21\x27\x6c\x0a\x00\x67\x15\xb1\xdd" "\x24\xab\x77\xa3\x9e\xd8\xc2\xa4\xda\x5a\xb8\x2a\xfb\x82\x03" "\x30\xe4\xfe", 63); *(uint64_t*)0x202b0058 = (uint64_t)0x4; *(uint64_t*)0x20886fe0 = (uint64_t)0x20ee7f29; *(uint64_t*)0x20886fe8 = (uint64_t)0xd7; *(uint64_t*)0x20886ff0 = (uint64_t)0x2050cf58; *(uint64_t*)0x20886ff8 = (uint64_t)0x0; memcpy((void*)0x20ee7f29, "\x06\x00\x00\x00\xac\xd8\xd2\xa9\xdb\x76\xdd\x0e\xe4\x02\xac" "\x94\xa2\xc0\x23\x07\xd7\xba\x52\x66\x4d\xaa\xdd\xcd\x66\xb0" "\x76\x5b\x4c\x31\xdd\x36\x7e\x8b\xb4\x50\x81\x9c\x5d\x65\xdb" "\x8f\x69\xfe\xbe\x99\xf8\x73\x82\xd7\x7e\xbe\x61\x19\x0f\x6d" "\xd7\x2c\x71\xf1\x1c\x7b\x86\xa0\xc8\x4d\x45\xa5\x6b\x35\x44" "\xba\xa5\xef\x88\x2e\x7f\x71\x25\x34\xc1\xe7\xe1\x8c\x83\x94" "\xdb\x6f\xe9\x39\x82\xfd\x04\xff\xed\x6c\x86\x00\x52\xba\x88" "\x64\x82\x8a\x38\x15\x60\x29\xce\x3a\x13\x0b\x93\x49\x0e\x0b" "\x48\x48\xf7\x04\x5a\x9e\x0c\x14\x1f\x54\xf1\x58\xb9\x7a\xca" "\x9a\x5b\x7b\xc2\x6a\x1b\x22\xae\xeb\x04\x89\x98\xd4\x17\xc4" "\x82\x8b\x00\xcf\xf9\xfb\x0b\xf7\x4f\x6d\x74\xf4\x85\xfb\x40" "\x40\x40\x13\x44\xab\x9c\x9a\x1e\x4b\xda\x65\x20\x64\x09\x79" "\x11\x5e\x45\x0b\x66\x7f\x20\xd9\xf6\x5c\x7a\xe8\xb2\x8c\xf1" "\xa7\x63\x74\x41\xa5\xb8\xfd\x5d\x0b\x54\x74\x9f\x84\xce\x4d" "\xbf\x1f\x24\x6a\xca", 215); *(uint64_t*)0x208adf10 = (uint64_t)0x10; *(uint32_t*)0x208adf18 = (uint32_t)0x0; *(uint32_t*)0x208adf1c = (uint32_t)0x0; r[44] = syscall(__NR_sendmmsg, r[18], 0x209bffabul, 0x1ul, 0x0ul); } int main() { use_temporary_dir(); int pid = do_sandbox_namespace(0, false); int status = 0; while (waitpid(pid, &status, __WALL) != pid) { } return 0; }