diff options
| author | Greg Steuck <blackgnezdo@gmail.com> | 2018-12-10 22:39:44 -0800 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2018-12-11 07:39:44 +0100 |
| commit | d90f8af59cdcebab382707098f32c87f950ab5df (patch) | |
| tree | 6a356ee5a90047dd2398fc39c19241af73a4a27c | |
| parent | 4093e33b1338f274ae0062f555de9d6af8640d61 (diff) | |
executor: reapply setuid sandbox for bsd
* Revert "Revert "executor: add setuid sandbox for openbsd""
The problem is the low file descriptor limit.
This reverts commit 4093e33b1338f274ae0062f555de9d6af8640d61.
* executor/executor make sure the file descriptor limit is sufficient
| -rw-r--r-- | executor/common_bsd.h | 74 | ||||
| -rw-r--r-- | executor/executor.cc | 6 | ||||
| -rw-r--r-- | executor/executor_bsd.h | 19 | ||||
| -rw-r--r-- | pkg/csource/generated.go | 70 | ||||
| -rw-r--r-- | pkg/host/host_openbsd.go | 1 |
5 files changed, 151 insertions, 19 deletions
diff --git a/executor/common_bsd.h b/executor/common_bsd.h index 9c61917d7..53ffc8668 100644 --- a/executor/common_bsd.h +++ b/executor/common_bsd.h @@ -267,10 +267,42 @@ static long syz_extract_tcp_res(long a0, long a1, long a2) #endif #endif // GOOS_freebsd || GOOS_openbsd +#if SYZ_EXECUTOR || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NONE + +#include <sys/resource.h> +#include <unistd.h> + +static void sandbox_common() +{ + if (setsid() == -1) + fail("setsid failed"); + + // Some minimal sandboxing. + struct rlimit rlim; +#ifndef GOOS_openbsd + // Documented bug in OpenBSD. + // This causes frequent random aborts on netbsd. Reason unknown. + rlim.rlim_cur = rlim.rlim_max = 128 << 20; + setrlimit(RLIMIT_AS, &rlim); +#endif + 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); + rlim.rlim_cur = rlim.rlim_max = 256; // see kMaxFd + setrlimit(RLIMIT_NOFILE, &rlim); +} +#endif // SYZ_EXECUTOR || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NONE + #if SYZ_EXECUTOR || SYZ_SANDBOX_NONE static void loop(); static int do_sandbox_none(void) { + sandbox_common(); #if (GOOS_freebsd || GOOS_openbsd) && (SYZ_EXECUTOR || SYZ_TUN_ENABLE) initialize_tun(procid); #endif @@ -278,3 +310,45 @@ static int do_sandbox_none(void) return 0; } #endif // SYZ_EXECUTOR || SYZ_SANDBOX_NONE + +#if SYZ_EXECUTOR || SYZ_SANDBOX_SETUID + +#include <sys/resource.h> +#include <sys/wait.h> +#include <unistd.h> + +static int wait_for_loop(int pid) +{ + if (pid < 0) + fail("sandbox fork failed"); + debug("spawned loop pid %d\n", pid); + int status = 0; + while (waitpid(-1, &status, WUNTRACED) != pid) { + } + return WEXITSTATUS(status); +} + +#define SYZ_HAVE_SANDBOX_SETUID 1 +static int do_sandbox_setuid(void) +{ + int pid = fork(); + if (pid != 0) + return wait_for_loop(pid); + + sandbox_common(); +#if (GOOS_freebsd || GOOS_openbsd) && (SYZ_EXECUTOR || SYZ_TUN_ENABLE) + initialize_tun(procid); +#endif + + const int nobody = 65534; + if (setgroups(0, NULL)) + fail("failed to setgroups"); + if (setresgid(nobody, nobody, nobody)) + fail("failed to setresgid"); + if (setresuid(nobody, nobody, nobody)) + fail("failed to setresuid"); + + loop(); + doexit(1); +} +#endif // SYZ_EXECUTOR || SYZ_SANDBOX_SETUID diff --git a/executor/executor.cc b/executor/executor.cc index 6569326d3..d6e7b75b3 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -12,6 +12,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/resource.h> #include <time.h> #include <unistd.h> @@ -422,6 +423,11 @@ int main(int argc, char** argv) void setup_control_pipes() { + // Makes sure the file descriptor limit is sufficient. + struct rlimit rlim; + rlim.rlim_cur = rlim.rlim_max = kMaxFd; + setrlimit(RLIMIT_NOFILE, &rlim); + if (dup2(0, kInPipeFd) < 0) fail("dup2(0, kInPipeFd) failed"); if (dup2(1, kOutPipeFd) < 0) diff --git a/executor/executor_bsd.h b/executor/executor_bsd.h index 7119a3992..8f364ca13 100644 --- a/executor/executor_bsd.h +++ b/executor/executor_bsd.h @@ -21,25 +21,6 @@ static void os_init(int argc, char** argv, void* data, size_t data_size) if (mmap(data, data_size, prot, MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, 0) != data) fail("mmap of data segment failed"); - - // Some minimal sandboxing. - // TODO: this should go into common_bsd.h because csource needs this too. - struct rlimit rlim; -#if GOOS_netbsd - // This causes frequent random aborts on netbsd. Reason unknown. - rlim.rlim_cur = rlim.rlim_max = 128 << 20; - setrlimit(RLIMIT_AS, &rlim); -#endif - 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); - rlim.rlim_cur = rlim.rlim_max = 256; // see kMaxFd - setrlimit(RLIMIT_NOFILE, &rlim); } static long execute_syscall(const call_t* c, long a[kMaxArgs]) diff --git a/pkg/csource/generated.go b/pkg/csource/generated.go index 0c3ecb4e8..73b050355 100644 --- a/pkg/csource/generated.go +++ b/pkg/csource/generated.go @@ -636,10 +636,38 @@ static long syz_extract_tcp_res(long a0, long a1, long a2) #endif #endif +#if SYZ_EXECUTOR || SYZ_SANDBOX_SETUID || SYZ_SANDBOX_NONE + +#include <sys/resource.h> +#include <unistd.h> + +static void sandbox_common() +{ + if (setsid() == -1) + fail("setsid failed"); + struct rlimit rlim; +#ifndef GOOS_openbsd + rlim.rlim_cur = rlim.rlim_max = 128 << 20; + setrlimit(RLIMIT_AS, &rlim); +#endif + 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); + rlim.rlim_cur = rlim.rlim_max = 256; + setrlimit(RLIMIT_NOFILE, &rlim); +} +#endif + #if SYZ_EXECUTOR || SYZ_SANDBOX_NONE static void loop(); static int do_sandbox_none(void) { + sandbox_common(); #if (GOOS_freebsd || GOOS_openbsd) && (SYZ_EXECUTOR || SYZ_TUN_ENABLE) initialize_tun(procid); #endif @@ -648,6 +676,48 @@ static int do_sandbox_none(void) } #endif +#if SYZ_EXECUTOR || SYZ_SANDBOX_SETUID + +#include <sys/resource.h> +#include <sys/wait.h> +#include <unistd.h> + +static int wait_for_loop(int pid) +{ + if (pid < 0) + fail("sandbox fork failed"); + debug("spawned loop pid %d\n", pid); + int status = 0; + while (waitpid(-1, &status, WUNTRACED) != pid) { + } + return WEXITSTATUS(status); +} + +#define SYZ_HAVE_SANDBOX_SETUID 1 +static int do_sandbox_setuid(void) +{ + int pid = fork(); + if (pid != 0) + return wait_for_loop(pid); + + sandbox_common(); +#if (GOOS_freebsd || GOOS_openbsd) && (SYZ_EXECUTOR || SYZ_TUN_ENABLE) + initialize_tun(procid); +#endif + + const int nobody = 65534; + if (setgroups(0, NULL)) + fail("failed to setgroups"); + if (setresgid(nobody, nobody, nobody)) + fail("failed to setresgid"); + if (setresuid(nobody, nobody, nobody)) + fail("failed to setresuid"); + + loop(); + doexit(1); +} +#endif + #elif GOOS_fuchsia #include <fcntl.h> diff --git a/pkg/host/host_openbsd.go b/pkg/host/host_openbsd.go index f750929a5..35e8a0298 100644 --- a/pkg/host/host_openbsd.go +++ b/pkg/host/host_openbsd.go @@ -14,4 +14,5 @@ func isSupported(c *prog.Syscall, sandbox string) (bool, string) { func init() { checkFeature[FeatureCoverage] = unconditionallyEnabled checkFeature[FeatureNetworkInjection] = unconditionallyEnabled + checkFeature[FeatureSandboxSetuid] = unconditionallyEnabled } |
