Created
November 20, 2017 12:59
-
-
Save dvyukov/629543c9abc19576fec66ce8fae130c7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// autogenerated by syzkaller (http://github.com/google/syzkaller) | |
#define _GNU_SOURCE | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <linux/capability.h> | |
#include <sched.h> | |
#include <signal.h> | |
#include <stdarg.h> | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <sys/mman.h> | |
#include <sys/mount.h> | |
#include <sys/prctl.h> | |
#include <sys/resource.h> | |
#include <sys/stat.h> | |
#include <sys/syscall.h> | |
#include <sys/time.h> | |
#include <sys/wait.h> | |
#include <unistd.h> | |
__attribute__((noreturn)) static void doexit(int status) | |
{ | |
volatile unsigned i; | |
syscall(__NR_exit_group, status); | |
for (i = 0;; i++) { | |
} | |
} | |
#include <errno.h> | |
#include <stdarg.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
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); | |
} | |
static void test(); | |
void loop() | |
{ | |
while (1) { | |
test(); | |
} | |
} | |
long r[40]; | |
void test() | |
{ | |
memset(r, -1, sizeof(r)); | |
r[0] = syscall(__NR_mmap, 0x20000000ul, 0xfff000ul, 0x3ul, 0x32ul, | |
0xfffffffffffffffful, 0x0ul); | |
*(uint32_t*)0x2000a000 = (uint32_t)0x1; | |
*(uint32_t*)0x2000a004 = (uint32_t)0x78; | |
*(uint8_t*)0x2000a008 = (uint8_t)0x0; | |
*(uint8_t*)0x2000a009 = (uint8_t)0xffffffffffffffff; | |
*(uint8_t*)0x2000a00a = (uint8_t)0x0; | |
*(uint8_t*)0x2000a00b = (uint8_t)0x0; | |
*(uint32_t*)0x2000a00c = (uint32_t)0x0; | |
*(uint64_t*)0x2000a010 = (uint64_t)0x5; | |
*(uint64_t*)0x2000a018 = (uint64_t)0x0; | |
*(uint64_t*)0x2000a020 = (uint64_t)0x7ffffffffc; | |
*(uint8_t*)0x2000a028 = (uint8_t)0x7f; | |
*(uint8_t*)0x2000a029 = (uint8_t)0x1000; | |
*(uint8_t*)0x2000a02a = (uint8_t)0x0; | |
*(uint8_t*)0x2000a02b = (uint8_t)0x0; | |
*(uint32_t*)0x2000a02c = (uint32_t)0x0; | |
*(uint32_t*)0x2000a030 = (uint32_t)0x0; | |
*(uint32_t*)0x2000a034 = (uint32_t)0x0; | |
*(uint64_t*)0x2000a038 = (uint64_t)0x6; | |
*(uint64_t*)0x2000a040 = (uint64_t)0x4; | |
*(uint64_t*)0x2000a048 = (uint64_t)0x200000004; | |
*(uint64_t*)0x2000a050 = (uint64_t)0x401; | |
*(uint64_t*)0x2000a058 = (uint64_t)0x800; | |
*(uint32_t*)0x2000a060 = (uint32_t)0x0; | |
*(uint64_t*)0x2000a068 = (uint64_t)0x80000000; | |
*(uint32_t*)0x2000a070 = (uint32_t)0x80000000000000; | |
*(uint16_t*)0x2000a074 = (uint16_t)0x0; | |
*(uint16_t*)0x2000a076 = (uint16_t)0x0; | |
r[28] = syscall(__NR_perf_event_open, 0x2000a000ul, 0x0ul, 0x0ul, | |
0xfffffffffffffffful, 0xeul); | |
memcpy((void*)0x20424000, "\x2e\x2f\x66\x69\x6c\x65\x30\x00", 8); | |
r[30] = syscall(__NR_mkdir, 0x20424000ul, 0x0ul); | |
memcpy((void*)0x20144000, "\x2e\x2f\x66\x69\x6c\x65\x30\x00", 8); | |
memcpy((void*)0x20343ff8, "\x2e\x2f\x66\x69\x6c\x65\x30\x00", 8); | |
memcpy((void*)0x20fb5ffc, "\x6e\x66\x73\x00", 4); | |
r[34] = syscall(__NR_mount, 0x20144000ul, 0x20343ff8ul, 0x20fb5ffcul, | |
0x0ul, 0x2000a000ul); | |
r[35] = syscall(__NR_socket, 0x10ul, 0x3ul, 0x0ul); | |
*(uint64_t*)0x20030000 = (uint64_t)0x20d24fd7; | |
*(uint64_t*)0x20030008 = (uint64_t)0x29; | |
memcpy((void*)0x20d24fd7, | |
"\x29\x00\x00\x00\x18\x00\xff\xfd\xfe\xff\x85\x00\x00\x0a\x00" | |
"\x21\x02\x00\x06\x00\x00\x00\x00\x07\x00\x00\x00\x00\x09\x00" | |
"\x08\x00\x05\x00\x0a\x00\x00\x00\x00\xc0\x00", | |
41); | |
r[39] = syscall(__NR_writev, r[35], 0x20030000ul, 0x1ul); | |
} | |
int main() | |
{ | |
use_temporary_dir(); | |
int pid = do_sandbox_namespace(0, false); | |
int status = 0; | |
while (waitpid(pid, &status, __WALL) != pid) { | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment