diff options
| author | Andrey Konovalov <andreyknvl@google.com> | 2017-01-31 18:40:10 +0100 |
|---|---|---|
| committer | Andrey Konovalov <andreyknvl@google.com> | 2017-01-31 18:40:10 +0100 |
| commit | f3bb6d96be685a64af8050d57f5ced7ec75da2e0 (patch) | |
| tree | 39482b00bb34df5bd7e4730ac6c423ec2603f5bf | |
| parent | dd4e19c77a5326ec907cdf89df0cf9fc41aa17d9 (diff) | |
executor: fix tun initialization when sandbox != none
| -rw-r--r-- | csource/common.go | 39 | ||||
| -rw-r--r-- | csource/csource.go | 12 | ||||
| -rw-r--r-- | executor/common.h | 42 | ||||
| -rw-r--r-- | executor/executor.cc | 8 |
4 files changed, 63 insertions, 38 deletions
diff --git a/csource/common.go b/csource/common.go index 2fbe81ec8..a0256ad50 100644 --- a/csource/common.go +++ b/csource/common.go @@ -189,12 +189,14 @@ static void execute_command(const char* format, ...) { va_list args; char command[COMMAND_MAX_LEN]; + int rv; va_start(args, format); vsnprintf_check(command, sizeof(command), format, args); - if (system(command) < 0) - fail("tun: command \"%s\" failed", &command[0]); + rv = system(command); + if (rv != 0) + fail("tun: command \"%s\" failed with code %d", &command[0], rv); va_end(args); } @@ -215,9 +217,6 @@ int tunfd = -1; static void initialize_tun(uint64_t pid) { - if (getuid() != 0) - return; - if (pid >= MAX_PIDS) fail("tun: no more than %d executors", MAX_PIDS); int id = pid; @@ -259,6 +258,13 @@ static void initialize_tun(uint64_t pid) execute_command("ip link set %s up", iface); } +static void setup_tun(uint64_t pid, bool enable_tun) { +#ifdef __NR_syz_emit_ethernet + if (enable_tun) + initialize_tun(pid); +#endif +} + static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) { if (tunfd < 0) @@ -1354,7 +1360,7 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a } } -static void setup_main_process(uint64_t pid, bool enable_tun) +static void setup_main_process() { struct sigaction sa; memset(&sa, 0, sizeof(sa)); @@ -1363,11 +1369,6 @@ static void setup_main_process(uint64_t pid, bool enable_tun) syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8); install_segv_handler(); -#ifdef __NR_syz_emit_ethernet - if (enable_tun) - initialize_tun(pid); -#endif - char tmpdir_template[] = "./syzkaller.XXXXXX"; char* tmpdir = mkdtemp(tmpdir_template); if (!tmpdir) @@ -1402,25 +1403,29 @@ static void sandbox_common() } #if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) -static int do_sandbox_none() +static int do_sandbox_none(int executor_pid, bool enable_tun) { int pid = fork(); if (pid) return pid; + sandbox_common(); + setup_tun(executor_pid, enable_tun); + loop(); doexit(1); } #endif #if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_SETUID) -static int do_sandbox_setuid() +static int do_sandbox_setuid(int executor_pid, bool enable_tun) { int pid = fork(); if (pid) return pid; sandbox_common(); + setup_tun(executor_pid, enable_tun); const int nobody = 65534; if (setgroups(0, NULL)) @@ -1438,6 +1443,8 @@ static int do_sandbox_setuid() #if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE) static int real_uid; static int real_gid; +static int epid; +static bool etun; __attribute__((aligned(64 << 10))) static char sandbox_stack[1 << 20]; static bool write_file(const char* file, const char* what, ...) @@ -1471,6 +1478,8 @@ static int namespace_sandbox_proc(void* arg) if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid)) fail("write of /proc/self/gid_map failed"); + setup_tun(epid, etun); + if (mkdir("./syz-tmp", 0777)) fail("mkdir(syz-tmp) failed"); if (mount("", "./syz-tmp", "tmpfs", 0, NULL)) @@ -1514,10 +1523,12 @@ static int namespace_sandbox_proc(void* arg) doexit(1); } -static int do_sandbox_namespace() +static int do_sandbox_namespace(int executor_pid, bool enable_tun) { real_uid = getuid(); real_gid = getgid(); + epid = executor_pid; + etun = enable_tun; mprotect(sandbox_stack, 4096, PROT_NONE); return clone(namespace_sandbox_proc, &sandbox_stack[sizeof(sandbox_stack) - 8], CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNET, NULL); diff --git a/csource/csource.go b/csource/csource.go index 183c787ab..853ba2a0c 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -68,8 +68,8 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { generateTestFunc(w, opts, calls, "loop") fmt.Fprint(w, "int main()\n{\n") - fmt.Fprintf(w, "\tsetup_main_process(0, %v);\n", enableTun) - fmt.Fprintf(w, "\tint pid = do_sandbox_%v();\n", opts.Sandbox) + fmt.Fprintf(w, "\tsetup_main_process();\n") + fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, enableTun) fmt.Fprint(w, "\tint status = 0;\n") fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") fmt.Fprint(w, "\treturn 0;\n}\n") @@ -77,8 +77,8 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { generateTestFunc(w, opts, calls, "test") if opts.Procs <= 1 { fmt.Fprint(w, "int main()\n{\n") - fmt.Fprintf(w, "\tsetup_main_process(0, %v);\n", enableTun) - fmt.Fprintf(w, "\tint pid = do_sandbox_%v();\n", opts.Sandbox) + fmt.Fprintf(w, "\tsetup_main_process();\n") + fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, enableTun) fmt.Fprint(w, "\tint status = 0;\n") fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n") fmt.Fprint(w, "\treturn 0;\n}\n") @@ -87,8 +87,8 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) { fmt.Fprint(w, "\tint i;") fmt.Fprintf(w, "\tfor (i = 0; i < %v; i++) {\n", opts.Procs) fmt.Fprint(w, "\t\tif (fork() == 0) {\n") - fmt.Fprintf(w, "\t\t\tsetup_main_process(i, %v);\n", enableTun) - fmt.Fprintf(w, "\t\t\tdo_sandbox_%v();\n", opts.Sandbox) + fmt.Fprintf(w, "\t\t\tsetup_main_process();\n") + fmt.Fprintf(w, "\t\t\tdo_sandbox_%v(i, %v);\n", opts.Sandbox, enableTun) fmt.Fprint(w, "\t\t\treturn 0;\n") fmt.Fprint(w, "\t\t}\n") fmt.Fprint(w, "\t}\n") diff --git a/executor/common.h b/executor/common.h index 10b3ea5bf..f32ed44a7 100644 --- a/executor/common.h +++ b/executor/common.h @@ -211,12 +211,14 @@ static void execute_command(const char* format, ...) { va_list args; char command[COMMAND_MAX_LEN]; + int rv; va_start(args, format); vsnprintf_check(command, sizeof(command), format, args); - if (system(command) < 0) - fail("tun: command \"%s\" failed", &command[0]); + rv = system(command); + if (rv != 0) + fail("tun: command \"%s\" failed with code %d", &command[0], rv); va_end(args); } @@ -238,9 +240,6 @@ int tunfd = -1; static void initialize_tun(uint64_t pid) { - if (getuid() != 0) - return; - if (pid >= MAX_PIDS) fail("tun: no more than %d executors", MAX_PIDS); int id = pid; @@ -282,6 +281,14 @@ static void initialize_tun(uint64_t pid) execute_command("ip link set %s up", iface); } +static void setup_tun(uint64_t pid, bool enable_tun) +{ +#ifdef __NR_syz_emit_ethernet + if (enable_tun) + initialize_tun(pid); +#endif +} + static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) { if (tunfd < 0) @@ -436,7 +443,7 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a } } -static void setup_main_process(uint64_t pid, bool enable_tun) +static void setup_main_process() { // Don't need that SIGCANCEL/SIGSETXID glibc stuff. // SIGCANCEL sent to main thread causes it to exit @@ -448,11 +455,6 @@ static void setup_main_process(uint64_t pid, bool enable_tun) syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8); install_segv_handler(); -#ifdef __NR_syz_emit_ethernet - if (enable_tun) - initialize_tun(pid); -#endif - char tmpdir_template[] = "./syzkaller.XXXXXX"; char* tmpdir = mkdtemp(tmpdir_template); if (!tmpdir) @@ -488,25 +490,29 @@ static void sandbox_common() } #if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NONE) -static int do_sandbox_none() +static int do_sandbox_none(int executor_pid, bool enable_tun) { int pid = fork(); if (pid) return pid; + sandbox_common(); + setup_tun(executor_pid, enable_tun); + loop(); doexit(1); } #endif #if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_SETUID) -static int do_sandbox_setuid() +static int do_sandbox_setuid(int executor_pid, bool enable_tun) { int pid = fork(); if (pid) return pid; sandbox_common(); + setup_tun(executor_pid, enable_tun); const int nobody = 65534; if (setgroups(0, NULL)) @@ -524,6 +530,8 @@ static int do_sandbox_setuid() #if defined(SYZ_EXECUTOR) || defined(SYZ_SANDBOX_NAMESPACE) static int real_uid; static int real_gid; +static int epid; +static bool etun; __attribute__((aligned(64 << 10))) static char sandbox_stack[1 << 20]; static bool write_file(const char* file, const char* what, ...) @@ -558,6 +566,10 @@ static int namespace_sandbox_proc(void* arg) if (!write_file("/proc/self/gid_map", "0 %d 1\n", real_gid)) fail("write of /proc/self/gid_map failed"); + // For sandbox namespace we setup tun after initializing uid mapping, + // otherwise ip commands fail. + setup_tun(epid, etun); + if (mkdir("./syz-tmp", 0777)) fail("mkdir(syz-tmp) failed"); if (mount("", "./syz-tmp", "tmpfs", 0, NULL)) @@ -605,10 +617,12 @@ static int namespace_sandbox_proc(void* arg) doexit(1); } -static int do_sandbox_namespace() +static int do_sandbox_namespace(int executor_pid, bool enable_tun) { real_uid = getuid(); real_gid = getgid(); + epid = executor_pid; + etun = enable_tun; mprotect(sandbox_stack, 4096, PROT_NONE); // to catch stack underflows return clone(namespace_sandbox_proc, &sandbox_stack[sizeof(sandbox_stack) - 8], CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWNET, NULL); diff --git a/executor/executor.cc b/executor/executor.cc index f228e1d74..7b7079706 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -164,18 +164,18 @@ int main(int argc, char** argv) uint64_t executor_pid = *((uint64_t*)input_data + 1); cover_open(); - setup_main_process(executor_pid, flag_enable_tun); + setup_main_process(); int pid = -1; switch (flag_sandbox) { case sandbox_none: - pid = do_sandbox_none(); + pid = do_sandbox_none(executor_pid, flag_enable_tun); break; case sandbox_setuid: - pid = do_sandbox_setuid(); + pid = do_sandbox_setuid(executor_pid, flag_enable_tun); break; case sandbox_namespace: - pid = do_sandbox_namespace(); + pid = do_sandbox_namespace(executor_pid, flag_enable_tun); break; default: fail("unknown sandbox type"); |
