From 0750245eea6b2b4dd4bb4f4f974beeb2a900c1d6 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Tue, 20 Oct 2015 17:43:02 +0200 Subject: experimental functionality to impersonate nobody user in executor --- executor/executor.cc | 28 +++++++++++++++++++++++++++- ipc/ipc.go | 14 +++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/executor/executor.cc b/executor/executor.cc index a8804994a..a266f54c1 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "syscalls.h" @@ -45,6 +46,7 @@ bool flag_debug; bool flag_cover; bool flag_threaded; bool flag_deduplicate; +bool flag_drop_privs; __attribute__((aligned(64 << 10))) char input_data[kMaxInput]; __attribute__((aligned(64 << 10))) char output_data[kMaxOutput]; @@ -81,6 +83,7 @@ int cover_fd; __attribute__((noreturn)) void fail(const char* msg, ...); __attribute__((noreturn)) void error(const char* msg, ...); +__attribute__((noreturn)) void exitf(const char* msg, ...); void debug(const char* msg, ...); uint64_t read_input(uint64_t** input_posp); uint64_t read_arg(uint64_t** input_posp); @@ -111,6 +114,7 @@ int main() flag_cover = flags & (1 << 1); flag_threaded = flags & (1 << 2); flag_deduplicate = flags & (1 << 3); + flag_drop_privs = flags & (1 << 4); output_pos = (uint32_t*)&output_data[0]; write_output(0); // Number of executed syscalls (updated later). @@ -118,6 +122,16 @@ int main() if (!flag_threaded) cover_init(&threads[0]); + if (flag_drop_privs) { + // TODO: 65534 is meant to be nobody + if (setgroups(0, NULL)) + fail("failed to setgroups"); + if (setresgid(65534, 65534, 65534)) + fail("failed to setresgid"); + if (setresuid(65534, 65534, 65534)) + fail("failed to setresuid"); + } + int call_index = 0; for (int n = 0;; n++) { uint64_t call_num = read_input(&input_pos); @@ -212,7 +226,7 @@ thread_t* schedule_call(int n, int call_index, int call_num, uint64_t num_args, th->handled = true; if (flag_threaded) { if (pthread_create(&th->th, 0, worker_thread, th)) - fail("pthread_create failed"); + exitf("pthread_create failed"); } } if (__atomic_load_n(&th->done, __ATOMIC_ACQUIRE)) { @@ -496,6 +510,18 @@ void error(const char* msg, ...) exit(68); } +// just exit (e.g. due to temporal ENOMEM error) +void exitf(const char* msg, ...) +{ + fflush(stdout); + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); + fprintf(stderr, "\n"); + exit(1); +} + void debug(const char* msg, ...) { if (!flag_debug) diff --git a/ipc/ipc.go b/ipc/ipc.go index 511398a7f..44a232048 100644 --- a/ipc/ipc.go +++ b/ipc/ipc.go @@ -34,6 +34,7 @@ const ( FlagCover // collect coverage FlagThreaded // use multiple threads to mitigate blocked syscalls FlagDedupCover // deduplicate coverage in executor + FlagDropPrivs // impersonate nobody user FlagStrace // run executor under strace ) @@ -42,11 +43,20 @@ func MakeEnv(bin string, timeout time.Duration, flags uint64) (*Env, error) { if err != nil { return nil, err } + defer func() { + if inf != nil { + closeMapping(inf, inmem) + } + }() outf, outmem, err := createMapping(16 << 20) if err != nil { - closeMapping(inf, inmem) return nil, err } + defer func() { + if outf != nil { + closeMapping(outf, outmem) + } + }() for i := 0; i < 8; i++ { inmem[i] = byte(flags >> (8 * uint(i))) } @@ -63,6 +73,8 @@ func MakeEnv(bin string, timeout time.Duration, flags uint64) (*Env, error) { if len(env.bin) == 0 { return nil, fmt.Errorf("binary is empty string") } + inf = nil + outf = nil return env, nil } -- cgit mrf-deployment