From 673349c42ec5e07c0fdb54d2a45f7b104865325b Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 18 Jul 2013 18:03:10 +0300 Subject: [PATCH 01/81] Repair of some of the lost parameter filters history --- src/common/sandbox.c | 106 +++++++++++++++++++++++++++++++++++++------ src/common/sandbox.h | 8 ++++ 2 files changed, 100 insertions(+), 14 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 68be89e881..56feae008d 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -25,11 +25,18 @@ #if defined(USE_LIBSECCOMP) +#include #include #include #include #include +static ParFilter param_filter[] = { + // Example entries + {SCMP_SYS(execve), "/usr/local/bin/tor", 0}, + {SCMP_SYS(execve), "/usr/local/bin/tor", 0} +}; + /** Variable used for storing all syscall numbers that will be allowed with the * stage 1 general Tor sandbox. */ @@ -142,24 +149,62 @@ static int general_filter[] = { SCMP_SYS(unlink) }; -/** - * Function responsible for setting up and enabling a global syscall filter. - * The function is a prototype developed for stage 1 of sandboxing Tor. - * Returns 0 on success. - */ static int -install_glob_syscall_filter(void) +add_param_filter(scmp_filter_ctx ctx) { - int rc = 0, i, filter_size; - scmp_filter_ctx ctx; + int i, filter_size, param_size, rc = 0; + void *map = NULL; - ctx = seccomp_init(SCMP_ACT_TRAP); - if (ctx == NULL) { - log_err(LD_BUG,"(Sandbox) failed to initialise libseccomp context"); - rc = -1; - goto end; + if (param_filter != NULL) { + filter_size = sizeof(param_filter) / sizeof(param_filter[0]); + } else { + filter_size = 0; } + // for each parameter filter + for (i = 0; i < filter_size; i++) { + if (!param_filter[i].prot) { + // allocating protected memory region for parameter + param_size = 1 + strnlen(param_filter[i].param, MAX_PARAM_LEN); + if (param_size == MAX_PARAM_LEN) { + log_warn(LD_BUG, "(Sandbox) Parameter %i length too large!", i); + } + + map = mmap(NULL, param_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | + MAP_ANON, -1, 0); + if (!map) { + log_err(LD_BUG,"(Sandbox) failed allocate protected memory!"); + return -1; + } + + // copying from non protected to protected + pointer reassign + memcpy(map, param_filter[i].param, param_size); + param_filter[i].param = map; + + // protecting from writes + if (mprotect(param_filter[i].param, param_size, PROT_READ)) { + log_err(LD_BUG,"(Sandbox) failed to protect memory!"); + return -1; + } + } // if not protected + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, param_filter[i].syscall, 1, + param_filter[i].param); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add syscall index %d, " + "received libseccomp error %d", i, rc); + return rc; + } + } + + return 0; +} + +static int +add_noparam_filter(scmp_filter_ctx ctx) +{ + int i, filter_size, rc = 0; + if (general_filter != NULL) { filter_size = sizeof(general_filter) / sizeof(general_filter[0]); } else { @@ -172,10 +217,43 @@ install_glob_syscall_filter(void) if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add syscall index %d, " "received libseccomp error %d", i, rc); - goto end; + return rc; } } + return 0; +} + +/** + * Function responsible for setting up and enabling a global syscall filter. + * The function is a prototype developed for stage 1 of sandboxing Tor. + * Returns 0 on success. + */ +static int +install_glob_syscall_filter(void) +{ + int rc = 0; + scmp_filter_ctx ctx; + + ctx = seccomp_init(SCMP_ACT_TRAP); + if (ctx == NULL) { + log_err(LD_BUG,"(Sandbox) failed to initialise libseccomp context"); + rc = -1; + goto end; + } + + // add parameter filters + if ((rc = add_param_filter(ctx))) { + log_err(LD_BUG, "(Sandbox) failed to add param filters!"); + goto end; + } + + // adding filters with no parameters + if ((rc = add_noparam_filter(ctx))) { + log_err(LD_BUG, "(Sandbox) failed to add param filters!"); + goto end; + } + rc = seccomp_load(ctx); end: diff --git a/src/common/sandbox.h b/src/common/sandbox.h index bd6f0cfb47..cfbecebbd4 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -30,6 +30,14 @@ #define __USE_GNU #include +#define MAX_PARAM_LEN 32 + +typedef struct { + int syscall; + char *param; + char prot; +} ParFilter; + /** * Linux 32 bit definitions */ From e7e2efb717ecefbf7b6eb92760ff272cca0b6eee Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 18 Jul 2013 18:11:47 +0300 Subject: [PATCH 02/81] Added getter for protected parameter --- src/common/sandbox.c | 27 ++++++++++++++++++++++++++- src/common/sandbox.h | 1 + 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 56feae008d..f041012f26 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -16,6 +16,7 @@ #include "sandbox.h" #include "torlog.h" #include "orconfig.h" +#include "torint.h" #if defined(HAVE_SECCOMP_H) && defined(__linux__) #define USE_LIBSECCOMP @@ -149,6 +150,30 @@ static int general_filter[] = { SCMP_SYS(unlink) }; +char* +get_prot_param(char *param) +{ + int i, filter_size; + + if (param == NULL) + return NULL; + + if (param_filter == NULL) { + filter_size = 0; + } else { + filter_size = sizeof(param_filter) / sizeof(param_filter[0]); + } + + for (i = 0; i < filter_size; i++) { + if (param_filter[i].prot && !strncmp(param, param_filter[i].param, + MAX_PARAM_LEN)) { + return param_filter[i].param; + } + } + + return NULL; +} + static int add_param_filter(scmp_filter_ctx ctx) { @@ -189,7 +214,7 @@ add_param_filter(scmp_filter_ctx ctx) } // if not protected rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, param_filter[i].syscall, 1, - param_filter[i].param); + SCMP_A0(SCMP_CMP_EQ, (intptr_t) param_filter[i].param)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add syscall index %d, " "received libseccomp error %d", i, rc); diff --git a/src/common/sandbox.h b/src/common/sandbox.h index cfbecebbd4..4752f1a733 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -58,6 +58,7 @@ typedef struct { void sandbox_set_debugging_fd(int fd); int tor_global_sandbox(void); +char* get_prot_param(char *param); #endif /* SANDBOX_H_ */ From b0725c964bac405359148f69bab81a6cfd330c28 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 18 Jul 2013 18:28:10 +0300 Subject: [PATCH 03/81] git test.. --- src/common/sandbox.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index f041012f26..c71d5d1bc2 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -32,6 +32,7 @@ #include #include +// GIT TEST static ParFilter param_filter[] = { // Example entries {SCMP_SYS(execve), "/usr/local/bin/tor", 0}, From 8dfa5772e7853f6a0ede99fd0b9284b668ff5cbc Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 18 Jul 2013 18:28:55 +0300 Subject: [PATCH 04/81] (undo) git test.. --- src/common/sandbox.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index c71d5d1bc2..f041012f26 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -32,7 +32,6 @@ #include #include -// GIT TEST static ParFilter param_filter[] = { // Example entries {SCMP_SYS(execve), "/usr/local/bin/tor", 0}, From 7cf1dbfd51f17773e93b509d954371886243a0eb Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 23 Jul 2013 10:14:25 +0300 Subject: [PATCH 05/81] changed paramfilter type to intptr_t --- src/common/sandbox.c | 18 +++++++++--------- src/common/sandbox.h | 4 +++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index f041012f26..f757c8d8e2 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -34,8 +34,8 @@ static ParFilter param_filter[] = { // Example entries - {SCMP_SYS(execve), "/usr/local/bin/tor", 0}, - {SCMP_SYS(execve), "/usr/local/bin/tor", 0} + {SCMP_SYS(execve), (intptr_t)("/usr/local/bin/tor"), 0}, + {SCMP_SYS(execve), (intptr_t)("/usr/local/bin/tor"), 0} }; /** Variable used for storing all syscall numbers that will be allowed with the @@ -165,9 +165,9 @@ get_prot_param(char *param) } for (i = 0; i < filter_size; i++) { - if (param_filter[i].prot && !strncmp(param, param_filter[i].param, + if (param_filter[i].prot && !strncmp(param, (char*) param_filter[i].param, MAX_PARAM_LEN)) { - return param_filter[i].param; + return (char*)(param_filter[i].param); } } @@ -190,7 +190,7 @@ add_param_filter(scmp_filter_ctx ctx) for (i = 0; i < filter_size; i++) { if (!param_filter[i].prot) { // allocating protected memory region for parameter - param_size = 1 + strnlen(param_filter[i].param, MAX_PARAM_LEN); + param_size = 1 + strnlen((char*) param_filter[i].param, MAX_PARAM_LEN); if (param_size == MAX_PARAM_LEN) { log_warn(LD_BUG, "(Sandbox) Parameter %i length too large!", i); } @@ -203,18 +203,18 @@ add_param_filter(scmp_filter_ctx ctx) } // copying from non protected to protected + pointer reassign - memcpy(map, param_filter[i].param, param_size); - param_filter[i].param = map; + memcpy(map, (char*) param_filter[i].param, param_size); + param_filter[i].param = (intptr_t) map; // protecting from writes - if (mprotect(param_filter[i].param, param_size, PROT_READ)) { + if (mprotect((char*) param_filter[i].param, param_size, PROT_READ)) { log_err(LD_BUG,"(Sandbox) failed to protect memory!"); return -1; } } // if not protected rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, param_filter[i].syscall, 1, - SCMP_A0(SCMP_CMP_EQ, (intptr_t) param_filter[i].param)); + SCMP_A0(SCMP_CMP_EQ, param_filter[i].param)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add syscall index %d, " "received libseccomp error %d", i, rc); diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 4752f1a733..bfb7a730fe 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -22,6 +22,8 @@ #endif +#include "torint.h" + /** * Linux definitions */ @@ -34,7 +36,7 @@ typedef struct { int syscall; - char *param; + intptr_t param; // TODO: make this intptr_t to support multiple types char prot; } ParFilter; From 8b12170f23f4042610b3574b8edf3794fef245b4 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 23 Jul 2013 10:49:56 +0300 Subject: [PATCH 06/81] added support for numeric parameters, tested with rt_sigaction --- src/common/sandbox.c | 22 +++++++++++++++++----- src/common/sandbox.h | 8 +++++++- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index f757c8d8e2..7c732157c1 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -28,14 +28,25 @@ #include #include +#include #include #include #include static ParFilter param_filter[] = { // Example entries - {SCMP_SYS(execve), (intptr_t)("/usr/local/bin/tor"), 0}, - {SCMP_SYS(execve), (intptr_t)("/usr/local/bin/tor"), 0} + {SCMP_SYS(execve), PARAM_PTR, (intptr_t)("/usr/local/bin/tor"), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGINT), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGTERM), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGPIPE), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGUSR1), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGUSR2), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGHUP), 0}, +#ifdef SIGXFSZ + {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGXFSZ), 0}, +#endif + {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGCHLD), 0}, + }; /** Variable used for storing all syscall numbers that will be allowed with the @@ -101,7 +112,6 @@ static int general_filter[] = { SCMP_SYS(prctl), SCMP_SYS(read), SCMP_SYS(rename), - SCMP_SYS(rt_sigaction), SCMP_SYS(rt_sigprocmask), SCMP_SYS(rt_sigreturn), #ifdef __NR_sigreturn @@ -166,7 +176,7 @@ get_prot_param(char *param) for (i = 0; i < filter_size; i++) { if (param_filter[i].prot && !strncmp(param, (char*) param_filter[i].param, - MAX_PARAM_LEN)) { + MAX_PARAM_LEN) && param_filter[i].ptype == PARAM_PTR) { return (char*)(param_filter[i].param); } } @@ -188,7 +198,7 @@ add_param_filter(scmp_filter_ctx ctx) // for each parameter filter for (i = 0; i < filter_size; i++) { - if (!param_filter[i].prot) { + if (!param_filter[i].prot && param_filter[i].ptype == PARAM_PTR) { // allocating protected memory region for parameter param_size = 1 + strnlen((char*) param_filter[i].param, MAX_PARAM_LEN); if (param_size == MAX_PARAM_LEN) { @@ -213,6 +223,8 @@ add_param_filter(scmp_filter_ctx ctx) } } // if not protected + param_filter[i].prot = 1; + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, param_filter[i].syscall, 1, SCMP_A0(SCMP_CMP_EQ, param_filter[i].param)); if (rc != 0) { diff --git a/src/common/sandbox.h b/src/common/sandbox.h index bfb7a730fe..de5699e342 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -34,9 +34,15 @@ #define MAX_PARAM_LEN 32 +#define PARAM_PTR 0 +#define PARAM_NUM 1 + typedef struct { int syscall; - intptr_t param; // TODO: make this intptr_t to support multiple types + + char ptype; + intptr_t param; + char prot; } ParFilter; From c15d09293bdfc90e94ef34369205cc6db9882607 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 23 Jul 2013 14:01:53 +0300 Subject: [PATCH 07/81] added experimental support for open syscall path param --- src/common/compat.c | 1 + src/common/sandbox.c | 39 +++++++++++++++++++++++++++++++++------ src/common/sandbox.h | 2 +- src/or/routerlist.c | 2 +- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/common/compat.c b/src/common/compat.c index 69eb0643d0..5b153674ef 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -125,6 +125,7 @@ tor_open_cloexec(const char *path, int flags, unsigned mode) { int fd; #ifdef O_CLOEXEC + path = get_prot_param(path); fd = open(path, flags|O_CLOEXEC, mode); if (fd >= 0) return fd; diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 7c732157c1..143995d294 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -46,7 +46,34 @@ static ParFilter param_filter[] = { {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGXFSZ), 0}, #endif {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGCHLD), 0}, - + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/cached-certs"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/cached-consensus"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/unverified-consensus"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/cached-microdesc-consensus"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/cached-microdesc-consensus.tmp"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/cached-microdescs"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/cached-microdescs.new"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/unverified-microdesc-consensus"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/cached-descriptors"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/cached-descriptors.new"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/cached-extrainfo"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/state.tmp"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/unparseable-desc.tmp"), 0}, + {SCMP_SYS(open), PARAM_PTR, + (intptr_t)("/home/cristi/.tor/unparseable-desc"), 0}, }; /** Variable used for storing all syscall numbers that will be allowed with the @@ -106,7 +133,6 @@ static int general_filter[] = { SCMP_SYS(mprotect), SCMP_SYS(mremap), SCMP_SYS(munmap), - SCMP_SYS(open), SCMP_SYS(openat), SCMP_SYS(poll), SCMP_SYS(prctl), @@ -175,13 +201,14 @@ get_prot_param(char *param) } for (i = 0; i < filter_size; i++) { - if (param_filter[i].prot && !strncmp(param, (char*) param_filter[i].param, - MAX_PARAM_LEN) && param_filter[i].ptype == PARAM_PTR) { + if (param_filter[i].prot && param_filter[i].ptype == PARAM_PTR + && !strncmp(param, (char*)(param_filter[i].param), MAX_PARAM_LEN)) { return (char*)(param_filter[i].param); } } - return NULL; + log_warn(LD_BUG, "(Sandbox) Parameter %s not found", param); + return param; } static int @@ -213,7 +240,7 @@ add_param_filter(scmp_filter_ctx ctx) } // copying from non protected to protected + pointer reassign - memcpy(map, (char*) param_filter[i].param, param_size); + memcpy(map, (char*) (param_filter[i].param), param_size); param_filter[i].param = (intptr_t) map; // protecting from writes diff --git a/src/common/sandbox.h b/src/common/sandbox.h index de5699e342..b973d9716e 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -32,7 +32,7 @@ #define __USE_GNU #include -#define MAX_PARAM_LEN 32 +#define MAX_PARAM_LEN 64 #define PARAM_PTR 0 #define PARAM_NUM 1 diff --git a/src/or/routerlist.c b/src/or/routerlist.c index a145ba716e..465aaedb13 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -37,7 +37,7 @@ #include "routerlist.h" #include "routerparse.h" #include "routerset.h" - +#include "../common/sandbox.h" // #define DEBUG_ROUTERLIST /****************************************************************************/ From e1410f20d749e3e76a28b7db0e99f51b863100ef Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 23 Jul 2013 14:22:31 +0300 Subject: [PATCH 08/81] added support for multiple parameters --- src/common/sandbox.c | 48 ++++++++++++++++++++++---------------------- src/common/sandbox.h | 1 + 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 143995d294..377ac062f3 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -35,44 +35,44 @@ static ParFilter param_filter[] = { // Example entries - {SCMP_SYS(execve), PARAM_PTR, (intptr_t)("/usr/local/bin/tor"), 0}, - {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGINT), 0}, - {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGTERM), 0}, - {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGPIPE), 0}, - {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGUSR1), 0}, - {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGUSR2), 0}, - {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGHUP), 0}, + {SCMP_SYS(execve), PARAM_PTR, 0, (intptr_t)("/usr/local/bin/tor"), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGINT), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGTERM), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGPIPE), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGUSR1), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGUSR2), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGHUP), 0}, #ifdef SIGXFSZ - {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGXFSZ), 0}, + {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGXFSZ), 0}, #endif - {SCMP_SYS(rt_sigaction), PARAM_NUM, (intptr_t)(SIGCHLD), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGCHLD), 0}, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/cached-certs"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/cached-consensus"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/unverified-consensus"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/cached-microdesc-consensus"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/cached-microdesc-consensus.tmp"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/cached-microdescs"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/cached-microdescs.new"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/unverified-microdesc-consensus"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/cached-descriptors"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/cached-descriptors.new"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/cached-extrainfo"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/state.tmp"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/unparseable-desc.tmp"), 0}, - {SCMP_SYS(open), PARAM_PTR, + {SCMP_SYS(open), PARAM_PTR, 0, (intptr_t)("/home/cristi/.tor/unparseable-desc"), 0}, }; @@ -253,7 +253,7 @@ add_param_filter(scmp_filter_ctx ctx) param_filter[i].prot = 1; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, param_filter[i].syscall, 1, - SCMP_A0(SCMP_CMP_EQ, param_filter[i].param)); + SCMP_CMP(param_filter[i].pindex, SCMP_CMP_EQ, param_filter[i].param)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add syscall index %d, " "received libseccomp error %d", i, rc); diff --git a/src/common/sandbox.h b/src/common/sandbox.h index b973d9716e..b80c19808e 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -41,6 +41,7 @@ typedef struct { int syscall; char ptype; + char pindex; intptr_t param; char prot; From 962d814e52beb8d3ca8c73f3ab48d8566778dcc5 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 24 Jul 2013 17:06:06 +0300 Subject: [PATCH 09/81] dynamic parameter filter (prototype, not tested) --- src/common/sandbox.c | 140 ++++++++++++++++++++++++++++++------------- src/common/sandbox.h | 15 ++++- 2 files changed, 112 insertions(+), 43 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 377ac062f3..2657cbaaf2 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -33,7 +33,9 @@ #include #include -static ParFilter param_filter[] = { +ParFilterDynamic *filter_dynamic = NULL; + +static ParFilterStatic filter_static[] = { // Example entries {SCMP_SYS(execve), PARAM_PTR, 0, (intptr_t)("/usr/local/bin/tor"), 0}, {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGINT), 0}, @@ -79,7 +81,7 @@ static ParFilter param_filter[] = { /** Variable used for storing all syscall numbers that will be allowed with the * stage 1 general Tor sandbox. */ -static int general_filter[] = { +static int filter_nopar_gen[] = { SCMP_SYS(access), SCMP_SYS(brk), SCMP_SYS(clock_gettime), @@ -194,16 +196,16 @@ get_prot_param(char *param) if (param == NULL) return NULL; - if (param_filter == NULL) { + if (filter_static == NULL) { filter_size = 0; } else { - filter_size = sizeof(param_filter) / sizeof(param_filter[0]); + filter_size = sizeof(filter_static) / sizeof(filter_static[0]); } for (i = 0; i < filter_size; i++) { - if (param_filter[i].prot && param_filter[i].ptype == PARAM_PTR - && !strncmp(param, (char*)(param_filter[i].param), MAX_PARAM_LEN)) { - return (char*)(param_filter[i].param); + if (filter_static[i].prot && filter_static[i].ptype == PARAM_PTR + && !strncmp(param, (char*)(filter_static[i].param), MAX_PARAM_LEN)) { + return (char*)(filter_static[i].param); } } @@ -211,49 +213,103 @@ get_prot_param(char *param) return param; } +static char* +prot_strdup(char* str) +{ + int param_size = 0; + char *res = NULL; + + if (str == NULL) + goto out; + + // allocating protected memory region for parameter + param_size = 1 + strnlen(str, MAX_PARAM_LEN); + if (param_size == MAX_PARAM_LEN) { + log_warn(LD_BUG, "(Sandbox) Parameter length too large!"); + } + + res = (char*) mmap(NULL, param_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | + MAP_ANON, -1, 0); + if (!res) { + log_err(LD_BUG,"(Sandbox) failed allocate protected memory!"); + goto out; + } + + // copying from non protected to protected + pointer reassign + memcpy(res, str, param_size); + + // protecting from writes + if (mprotect(res, param_size, PROT_READ)) { + log_err(LD_BUG,"(Sandbox) failed to protect memory!"); + return NULL; + } + + out: + return res; +} + +int +add_dynamic_param_filter(char *syscall, char ptype, char pindex, intptr_t val) +{ + ParFilterDynamic **elem; + + for (elem = &filter_dynamic; *elem != NULL; elem = &(*elem)->next); + + *elem = (ParFilterDynamic*) malloc(sizeof(ParFilterDynamic)); + (*elem)->next = NULL; + (*elem)->pindex = pindex; + (*elem)->ptype = ptype; + + switch (ptype) { + case PARAM_PTR: + (*elem)->param = (intptr_t) prot_strdup((char*) val); + (*elem)->prot = 1; + break; + + case PARAM_NUM: + (*elem)->param = val; + (*elem)->prot = 0; + break; + } + + return 0; +} + static int add_param_filter(scmp_filter_ctx ctx) { - int i, filter_size, param_size, rc = 0; - void *map = NULL; + int i, filter_size, rc = 0; + ParFilterDynamic *elem; - if (param_filter != NULL) { - filter_size = sizeof(param_filter) / sizeof(param_filter[0]); + if (filter_static != NULL) { + filter_size = sizeof(filter_static) / sizeof(filter_static[0]); } else { filter_size = 0; } - // for each parameter filter + // for each dynamic parameter filters + for (elem = filter_dynamic; elem != NULL; elem = elem->next) { + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, elem->syscall, 1, + SCMP_CMP(elem->pindex, SCMP_CMP_EQ, elem->param)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " + "error %d", rc); + return rc; + } + } + + // for each static parameter filter for (i = 0; i < filter_size; i++) { - if (!param_filter[i].prot && param_filter[i].ptype == PARAM_PTR) { - // allocating protected memory region for parameter - param_size = 1 + strnlen((char*) param_filter[i].param, MAX_PARAM_LEN); - if (param_size == MAX_PARAM_LEN) { - log_warn(LD_BUG, "(Sandbox) Parameter %i length too large!", i); - } + if (!filter_static[i].prot && filter_static[i].ptype == PARAM_PTR) { + filter_static[i].param = (intptr_t) prot_strdup( + (char*) (filter_static[i].param)); + } - map = mmap(NULL, param_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | - MAP_ANON, -1, 0); - if (!map) { - log_err(LD_BUG,"(Sandbox) failed allocate protected memory!"); - return -1; - } + filter_static[i].prot = 1; - // copying from non protected to protected + pointer reassign - memcpy(map, (char*) (param_filter[i].param), param_size); - param_filter[i].param = (intptr_t) map; - - // protecting from writes - if (mprotect((char*) param_filter[i].param, param_size, PROT_READ)) { - log_err(LD_BUG,"(Sandbox) failed to protect memory!"); - return -1; - } - } // if not protected - - param_filter[i].prot = 1; - - rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, param_filter[i].syscall, 1, - SCMP_CMP(param_filter[i].pindex, SCMP_CMP_EQ, param_filter[i].param)); + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, filter_static[i].syscall, 1, + SCMP_CMP(filter_static[i].pindex, SCMP_CMP_EQ, + filter_static[i].param)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add syscall index %d, " "received libseccomp error %d", i, rc); @@ -269,15 +325,15 @@ add_noparam_filter(scmp_filter_ctx ctx) { int i, filter_size, rc = 0; - if (general_filter != NULL) { - filter_size = sizeof(general_filter) / sizeof(general_filter[0]); + if (filter_nopar_gen != NULL) { + filter_size = sizeof(filter_nopar_gen) / sizeof(filter_nopar_gen[0]); } else { filter_size = 0; } // add general filters for (i = 0; i < filter_size; i++) { - rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, general_filter[i], 0); + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i], 0); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add syscall index %d, " "received libseccomp error %d", i, rc); diff --git a/src/common/sandbox.h b/src/common/sandbox.h index b80c19808e..b75161d93b 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -45,7 +45,20 @@ typedef struct { intptr_t param; char prot; -} ParFilter; +} ParFilterStatic; + +struct pfd_elem { + int syscall; + + char ptype; + char pindex; + intptr_t param; + + char prot; + + struct pfd_elem *next; +}; +typedef struct pfd_elem ParFilterDynamic; /** * Linux 32 bit definitions From abe082e7d03ad81d7f28d3f5c0070214aa525bfb Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 24 Jul 2013 17:15:57 +0300 Subject: [PATCH 10/81] dynamic parameter filter bug fixes --- src/common/sandbox.c | 15 +++++++++++++++ src/common/sandbox.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 2657cbaaf2..1a842f9ed8 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -192,6 +192,7 @@ char* get_prot_param(char *param) { int i, filter_size; + ParFilterDynamic *elem; if (param == NULL) return NULL; @@ -209,6 +210,13 @@ get_prot_param(char *param) } } + for (elem = filter_dynamic; elem != NULL; elem = elem->next) { + if (elem->prot && elem->ptype == PARAM_PTR + && !strncmp(param, (char*)(elem->param), MAX_PARAM_LEN)) { + return (char*)(elem->param); + } + } + log_warn(LD_BUG, "(Sandbox) Parameter %s not found", param); return param; } @@ -272,6 +280,13 @@ add_dynamic_param_filter(char *syscall, char ptype, char pindex, intptr_t val) break; } + // TODO: and so on ..? + if (!strcmp(syscall, "open")) { + (*elem)->syscall = SCMP_SYS(open); + } else if (!strcmp(syscall, "rt_sigaction")) { + (*elem)->syscall = SCMP_SYS(rt_sigaction); + } + return 0; } diff --git a/src/common/sandbox.h b/src/common/sandbox.h index b75161d93b..dc765c758e 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -81,6 +81,8 @@ typedef struct pfd_elem ParFilterDynamic; void sandbox_set_debugging_fd(int fd); int tor_global_sandbox(void); char* get_prot_param(char *param); +int add_dynamic_param_filter(char *syscall, char ptype, char pindex, + intptr_t val); #endif /* SANDBOX_H_ */ From 3dfe1c06396665d4008ba2ea54a0ad23d445df2b Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 25 Jul 2013 13:25:20 +0300 Subject: [PATCH 11/81] initia stages of runtime dynamic filters --- src/common/sandbox.c | 78 ++++++++++++-------------------------------- src/common/sandbox.h | 7 ++-- src/or/main.c | 40 +++++++++++++++++++++++ 3 files changed, 63 insertions(+), 62 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 1a842f9ed8..a4afc36fb5 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -33,9 +33,9 @@ #include #include -ParFilterDynamic *filter_dynamic = NULL; +sandbox_cfg_t *filter_dynamic = NULL; -static ParFilterStatic filter_static[] = { +static sandbox_static_cfg_t filter_static[] = { // Example entries {SCMP_SYS(execve), PARAM_PTR, 0, (intptr_t)("/usr/local/bin/tor"), 0}, {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGINT), 0}, @@ -48,34 +48,6 @@ static ParFilterStatic filter_static[] = { {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGXFSZ), 0}, #endif {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGCHLD), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/cached-certs"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/cached-consensus"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/unverified-consensus"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/cached-microdesc-consensus"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/cached-microdesc-consensus.tmp"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/cached-microdescs"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/cached-microdescs.new"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/unverified-microdesc-consensus"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/cached-descriptors"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/cached-descriptors.new"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/cached-extrainfo"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/state.tmp"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/unparseable-desc.tmp"), 0}, - {SCMP_SYS(open), PARAM_PTR, 0, - (intptr_t)("/home/cristi/.tor/unparseable-desc"), 0}, }; /** Variable used for storing all syscall numbers that will be allowed with the @@ -192,7 +164,7 @@ char* get_prot_param(char *param) { int i, filter_size; - ParFilterDynamic *elem; + sandbox_cfg_t *elem; if (param == NULL) return NULL; @@ -256,36 +228,26 @@ prot_strdup(char* str) return res; } -int -add_dynamic_param_filter(char *syscall, char ptype, char pindex, intptr_t val) +sandbox_cfg_t* +sandbox_cfg_new() { - ParFilterDynamic **elem; + return NULL; +} - for (elem = &filter_dynamic; *elem != NULL; elem = &(*elem)->next); +int +sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) +{ + sandbox_cfg_t *elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); - *elem = (ParFilterDynamic*) malloc(sizeof(ParFilterDynamic)); - (*elem)->next = NULL; - (*elem)->pindex = pindex; - (*elem)->ptype = ptype; + elem->syscall = SCMP_SYS(open); + elem->pindex = 0; + elem->ptype = PARAM_PTR; + elem->param = (intptr_t) prot_strdup((char*) file); + elem->prot = 1; - switch (ptype) { - case PARAM_PTR: - (*elem)->param = (intptr_t) prot_strdup((char*) val); - (*elem)->prot = 1; - break; - - case PARAM_NUM: - (*elem)->param = val; - (*elem)->prot = 0; - break; - } - - // TODO: and so on ..? - if (!strcmp(syscall, "open")) { - (*elem)->syscall = SCMP_SYS(open); - } else if (!strcmp(syscall, "rt_sigaction")) { - (*elem)->syscall = SCMP_SYS(rt_sigaction); - } + // fifo + elem->next = filter_dynamic; + filter_dynamic = elem; return 0; } @@ -294,7 +256,7 @@ static int add_param_filter(scmp_filter_ctx ctx) { int i, filter_size, rc = 0; - ParFilterDynamic *elem; + sandbox_cfg_t *elem; if (filter_static != NULL) { filter_size = sizeof(filter_static) / sizeof(filter_static[0]); diff --git a/src/common/sandbox.h b/src/common/sandbox.h index dc765c758e..2cb8ab8806 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -45,7 +45,7 @@ typedef struct { intptr_t param; char prot; -} ParFilterStatic; +} sandbox_static_cfg_t; struct pfd_elem { int syscall; @@ -58,7 +58,7 @@ struct pfd_elem { struct pfd_elem *next; }; -typedef struct pfd_elem ParFilterDynamic; +typedef struct pfd_elem sandbox_cfg_t; /** * Linux 32 bit definitions @@ -81,8 +81,7 @@ typedef struct pfd_elem ParFilterDynamic; void sandbox_set_debugging_fd(int fd); int tor_global_sandbox(void); char* get_prot_param(char *param); -int add_dynamic_param_filter(char *syscall, char ptype, char pindex, - intptr_t val); +int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file); #endif /* SANDBOX_H_ */ diff --git a/src/or/main.c b/src/or/main.c index 618ee6e13e..8bcf9277e7 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2639,6 +2639,43 @@ find_flashcard_path(PWCHAR path, size_t size) } #endif +static int +sandbox_cfg_init_open() +{ + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("cached-certs")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("cached-consensus")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("unverified-consensus")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("cached-microdesc-consensus")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("cached-microdesc-consensus.tmp")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("cached-microdescs")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("cached-microdescs.tmp")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("cached-microdescs.new")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("unverified-microdesc-consensus")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("cached-descriptors")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("cached-descriptors.new")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("cached-extrainfo")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("state.tmp")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("unparseable-desc.tmp")); + sandbox_cfg_allow_open_filename(NULL, + get_datadir_fname("unparseable-desc")); + + return 0; +} + /** Main entry point for the Tor process. Called from main(). */ /* This function is distinct from main() only so we can link main.c into * the unittest binary without conflicting with the unittests' main. */ @@ -2707,6 +2744,9 @@ tor_main(int argc, char *argv[]) return -1; if (get_options()->Sandbox) { + if (sandbox_cfg_init_open() < 0) + return -1; + if (tor_global_sandbox()) { log_err(LD_BUG,"Failed to create syscall sandbox filter"); return -1; From 626a2b23de006154b6cb3fa334a97dc547d56a98 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 25 Jul 2013 14:08:02 +0300 Subject: [PATCH 12/81] integrated context for dynamic filters --- src/common/sandbox.c | 48 ++++++++++++++++++++++++++++++++------------ src/common/sandbox.h | 3 +++ src/or/main.c | 43 ++++++++++++++++++++------------------- 3 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index a4afc36fb5..ce6b63c175 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -228,12 +228,6 @@ prot_strdup(char* str) return res; } -sandbox_cfg_t* -sandbox_cfg_new() -{ - return NULL; -} - int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) { @@ -253,7 +247,7 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) } static int -add_param_filter(scmp_filter_ctx ctx) +add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) { int i, filter_size, rc = 0; sandbox_cfg_t *elem; @@ -265,7 +259,8 @@ add_param_filter(scmp_filter_ctx ctx) } // for each dynamic parameter filters - for (elem = filter_dynamic; elem != NULL; elem = elem->next) { + elem = (cfg == NULL) ? filter_dynamic : cfg; + for (; elem != NULL; elem = elem->next) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, elem->syscall, 1, SCMP_CMP(elem->pindex, SCMP_CMP_EQ, elem->param)); if (rc != 0) { @@ -327,7 +322,7 @@ add_noparam_filter(scmp_filter_ctx ctx) * Returns 0 on success. */ static int -install_glob_syscall_filter(void) +install_syscall_filter(sandbox_cfg_t* cfg) { int rc = 0; scmp_filter_ctx ctx; @@ -340,7 +335,7 @@ install_glob_syscall_filter(void) } // add parameter filters - if ((rc = add_param_filter(ctx))) { + if ((rc = add_param_filter(ctx, cfg))) { log_err(LD_BUG, "(Sandbox) failed to add param filters!"); goto end; } @@ -450,12 +445,12 @@ install_sigsys_debugging(void) * into account various available features for different linux flavours. */ static int -initialise_libseccomp_sandbox(void) +initialise_libseccomp_sandbox(sandbox_cfg_t* cfg) { if (install_sigsys_debugging()) return -1; - if (install_glob_syscall_filter()) + if (install_syscall_filter(cfg)) return -2; return 0; @@ -463,6 +458,33 @@ initialise_libseccomp_sandbox(void) #endif // USE_LIBSECCOMP +sandbox_cfg_t* +sandbox_cfg_new() { + return NULL; +} + +int +sandbox_init(sandbox_cfg_t* cfg) +{ +#if defined(USE_LIBSECCOMP) + return initialise_libseccomp_sandbox(cfg); + +#elif defined(_WIN32) + log_warn(LD_BUG,"Windows sandboxing is not implemented. The feature is " + "currently disabled."); + return 0; + +#elif defined(TARGET_OS_MAC) + log_warn(LD_BUG,"Mac OSX sandboxing is not implemented. The feature is " + "currently disabled"); + return 0; +#else + log_warn(LD_BUG,"Sandboxing is not implemented for your platform. The " + "feature is currently disabled"); + return 0; +#endif +} + /** * Enables the stage 1 general sandbox. It applies a syscall filter which does * not restrict any Tor features. The filter is representative for the whole @@ -473,7 +495,7 @@ tor_global_sandbox(void) { #if defined(USE_LIBSECCOMP) - return initialise_libseccomp_sandbox(); + return initialise_libseccomp_sandbox(NULL); #elif defined(_WIN32) log_warn(LD_BUG,"Windows sandboxing is not implemented. The feature is " diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 2cb8ab8806..c6d80659e3 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -81,7 +81,10 @@ typedef struct pfd_elem sandbox_cfg_t; void sandbox_set_debugging_fd(int fd); int tor_global_sandbox(void); char* get_prot_param(char *param); + +sandbox_cfg_t * sandbox_cfg_new(); int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file); +int sandbox_init(sandbox_cfg_t* cfg); #endif /* SANDBOX_H_ */ diff --git a/src/or/main.c b/src/or/main.c index 8bcf9277e7..978c17127c 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2639,41 +2639,43 @@ find_flashcard_path(PWCHAR path, size_t size) } #endif -static int -sandbox_cfg_init_open() +static sandbox_cfg_t* +sandbox_init_filter() { - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_t *cfg = sandbox_cfg_new(); + + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-certs")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-consensus")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("unverified-consensus")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-microdesc-consensus")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-microdesc-consensus.tmp")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-microdescs")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-microdescs.tmp")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-microdescs.new")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("unverified-microdesc-consensus")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-descriptors")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-descriptors.new")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-extrainfo")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("state.tmp")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("unparseable-desc.tmp")); - sandbox_cfg_allow_open_filename(NULL, + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("unparseable-desc")); - return 0; + return cfg; } /** Main entry point for the Tor process. Called from main(). */ @@ -2744,10 +2746,9 @@ tor_main(int argc, char *argv[]) return -1; if (get_options()->Sandbox) { - if (sandbox_cfg_init_open() < 0) - return -1; + sandbox_cfg_t* cfg = sandbox_init_filter(); - if (tor_global_sandbox()) { + if (sandbox_init(cfg)) { log_err(LD_BUG,"Failed to create syscall sandbox filter"); return -1; } From 8f9d3da19447f138bc451937b20537810926ff30 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Fri, 26 Jul 2013 19:53:05 +0300 Subject: [PATCH 13/81] Investigated access4 syscall problem, small changes to filter. --- src/common/sandbox.c | 20 +++++++++----------- src/or/main.c | 2 ++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index ce6b63c175..4a3faa47cd 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -48,10 +48,16 @@ static sandbox_static_cfg_t filter_static[] = { {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGXFSZ), 0}, #endif {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGCHLD), 0}, + {SCMP_SYS(time), PARAM_NUM, 0, 0, 0}, }; /** Variable used for storing all syscall numbers that will be allowed with the * stage 1 general Tor sandbox. + * + * todo: + * read, write, close - rely on fd + * + * */ static int filter_nopar_gen[] = { SCMP_SYS(access), @@ -124,7 +130,6 @@ static int filter_nopar_gen[] = { #ifdef __NR_stat64 SCMP_SYS(stat64), #endif - SCMP_SYS(time), SCMP_SYS(uname), SCMP_SYS(write), SCMP_SYS(exit_group), @@ -137,27 +142,20 @@ static int filter_nopar_gen[] = { SCMP_SYS(getsockname), SCMP_SYS(getsockopt), SCMP_SYS(listen), -#if __NR_recv >= 0 - /* This is a kludge; It's necessary on 64-bit with libseccomp 1.0.0; I - * don't know if other 64-bit or other versions require it. */ SCMP_SYS(recv), -#endif SCMP_SYS(recvmsg), -#if __NR_send >= 0 - SCMP_SYS(send), -#endif SCMP_SYS(sendto), + SCMP_SYS(send), SCMP_SYS(setsockopt), SCMP_SYS(socket), SCMP_SYS(socketpair), - // TODO: remove when accept4 is fixed #ifdef __NR_socketcall - SCMP_SYS(socketcall), +// SCMP_SYS(socketcall), #endif SCMP_SYS(recvfrom), - SCMP_SYS(unlink) + SCMP_SYS(unlink), }; char* diff --git a/src/or/main.c b/src/or/main.c index 978c17127c..269d3fd9ba 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2660,6 +2660,8 @@ sandbox_init_filter() get_datadir_fname("cached-microdescs.tmp")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-microdescs.new")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname("cached-microdescs.new.tmp")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("unverified-microdesc-consensus")); sandbox_cfg_allow_open_filename(&cfg, From 6d5b0367f6e0035f99570b5bb76a75322ae9a85e Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 29 Jul 2013 14:46:47 +0300 Subject: [PATCH 14/81] Changes as suggested by nickm - char* to const char* and name refactoring - workaround for accept4 syscall --- src/common/compat.c | 2 +- src/common/sandbox.c | 15 +++++++-------- src/common/sandbox.h | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/common/compat.c b/src/common/compat.c index 5b153674ef..47b65d3560 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -125,7 +125,7 @@ tor_open_cloexec(const char *path, int flags, unsigned mode) { int fd; #ifdef O_CLOEXEC - path = get_prot_param(path); + path = sandbox_intern_string(path); fd = open(path, flags|O_CLOEXEC, mode); if (fd >= 0) return fd; diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 4a3faa47cd..2e8467d7c1 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -49,6 +49,10 @@ static sandbox_static_cfg_t filter_static[] = { #endif {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGCHLD), 0}, {SCMP_SYS(time), PARAM_NUM, 0, 0, 0}, + +#ifdef __NR_socketcall + {SCMP_SYS(socketcall), PARAM_NUM, 0, 18, 0}, // accept4 workaround +#endif }; /** Variable used for storing all syscall numbers that will be allowed with the @@ -136,7 +140,7 @@ static int filter_nopar_gen[] = { SCMP_SYS(exit), // socket syscalls - SCMP_SYS(accept4), +// SCMP_SYS(accept4), SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname), @@ -149,17 +153,12 @@ static int filter_nopar_gen[] = { SCMP_SYS(setsockopt), SCMP_SYS(socket), SCMP_SYS(socketpair), - -#ifdef __NR_socketcall -// SCMP_SYS(socketcall), -#endif - SCMP_SYS(recvfrom), SCMP_SYS(unlink), }; -char* -get_prot_param(char *param) +const char* +sandbox_intern_string(char *param) { int i, filter_size; sandbox_cfg_t *elem; diff --git a/src/common/sandbox.h b/src/common/sandbox.h index c6d80659e3..9acf8c4a97 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -80,7 +80,7 @@ typedef struct pfd_elem sandbox_cfg_t; void sandbox_set_debugging_fd(int fd); int tor_global_sandbox(void); -char* get_prot_param(char *param); +const char* sandbox_intern_string(char *param); sandbox_cfg_t * sandbox_cfg_new(); int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file); From 8022def6f05bf40e1c6e0fd15d77ed0ecf5c3406 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 29 Jul 2013 16:30:39 +0300 Subject: [PATCH 15/81] added openat parameter filter --- src/common/sandbox.c | 19 ++++++++++++++----- src/common/sandbox.h | 4 +++- src/common/util.c | 4 +++- src/or/main.c | 2 ++ 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 2e8467d7c1..efadeca84e 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -117,7 +117,6 @@ static int filter_nopar_gen[] = { SCMP_SYS(mprotect), SCMP_SYS(mremap), SCMP_SYS(munmap), - SCMP_SYS(openat), SCMP_SYS(poll), SCMP_SYS(prctl), SCMP_SYS(read), @@ -158,7 +157,7 @@ static int filter_nopar_gen[] = { }; const char* -sandbox_intern_string(char *param) +sandbox_intern_string(const char *param) { int i, filter_size; sandbox_cfg_t *elem; @@ -228,15 +227,25 @@ prot_strdup(char* str) int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) { - sandbox_cfg_t *elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); + sandbox_cfg_t *elem = NULL; + intptr_t prot_str = (intptr_t) prot_strdup((char*) file); + elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); elem->syscall = SCMP_SYS(open); elem->pindex = 0; elem->ptype = PARAM_PTR; - elem->param = (intptr_t) prot_strdup((char*) file); + elem->param = prot_str; elem->prot = 1; + elem->next = filter_dynamic; + filter_dynamic = elem; - // fifo + // also allow openat + elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); + elem->syscall = SCMP_SYS(openat); + elem->pindex = 1; + elem->ptype = PARAM_PTR; + elem->param = prot_str; + elem->prot = 1; elem->next = filter_dynamic; filter_dynamic = elem; diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 9acf8c4a97..104d832bc1 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -29,7 +29,9 @@ */ #ifdef __linux__ +#ifndef __USE_GNU #define __USE_GNU +#endif #include #define MAX_PARAM_LEN 64 @@ -80,7 +82,7 @@ typedef struct pfd_elem sandbox_cfg_t; void sandbox_set_debugging_fd(int fd); int tor_global_sandbox(void); -const char* sandbox_intern_string(char *param); +const char* sandbox_intern_string(const char *param); sandbox_cfg_t * sandbox_cfg_new(); int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file); diff --git a/src/common/util.c b/src/common/util.c index 651554ed23..75462b68a1 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -24,6 +24,7 @@ #include "torint.h" #include "container.h" #include "address.h" +#include "../common/sandbox.h" #ifdef _WIN32 #include @@ -3042,6 +3043,7 @@ smartlist_t * tor_listdir(const char *dirname) { smartlist_t *result; + const char *prot_dname = sandbox_intern_string(dirname); #ifdef _WIN32 char *pattern=NULL; TCHAR tpattern[MAX_PATH] = {0}; @@ -3085,7 +3087,7 @@ tor_listdir(const char *dirname) #else DIR *d; struct dirent *de; - if (!(d = opendir(dirname))) + if (!(d = opendir(prot_dname))) return NULL; result = smartlist_new(); diff --git a/src/or/main.c b/src/or/main.c index 269d3fd9ba..d50f239e67 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2644,6 +2644,8 @@ sandbox_init_filter() { sandbox_cfg_t *cfg = sandbox_cfg_new(); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname("cached-status")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-certs")); sandbox_cfg_allow_open_filename(&cfg, From 871e5b35a89ae02f92b64af0afb058fae9c41f43 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 30 Jul 2013 19:09:28 +0300 Subject: [PATCH 16/81] small filter changes; openat as separate function --- src/common/sandbox.c | 32 +++++++++++++++++++------------- src/common/sandbox.h | 1 + src/or/main.c | 3 ++- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index efadeca84e..8e7796bc5c 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -26,17 +26,21 @@ #if defined(USE_LIBSECCOMP) +#define _GNU_SOURCE + #include #include +#include #include + #include #include #include +#include sandbox_cfg_t *filter_dynamic = NULL; static sandbox_static_cfg_t filter_static[] = { - // Example entries {SCMP_SYS(execve), PARAM_PTR, 0, (intptr_t)("/usr/local/bin/tor"), 0}, {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGINT), 0}, {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGTERM), 0}, @@ -49,19 +53,16 @@ static sandbox_static_cfg_t filter_static[] = { #endif {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGCHLD), 0}, {SCMP_SYS(time), PARAM_NUM, 0, 0, 0}, - + // accept4 workaround #ifdef __NR_socketcall - {SCMP_SYS(socketcall), PARAM_NUM, 0, 18, 0}, // accept4 workaround + {SCMP_SYS(socketcall), PARAM_NUM, 0, 18, 0}, #endif + + {SCMP_SYS(open), PARAM_NUM, 1, O_RDONLY | O_CLOEXEC, 0} }; /** Variable used for storing all syscall numbers that will be allowed with the * stage 1 general Tor sandbox. - * - * todo: - * read, write, close - rely on fd - * - * */ static int filter_nopar_gen[] = { SCMP_SYS(access), @@ -72,7 +73,6 @@ static int filter_nopar_gen[] = { SCMP_SYS(epoll_create), SCMP_SYS(epoll_ctl), SCMP_SYS(epoll_wait), - SCMP_SYS(execve), SCMP_SYS(fcntl), #ifdef __NR_fcntl64 /* Older libseccomp versions don't define PNR entries for all of these, @@ -228,23 +228,29 @@ int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) { sandbox_cfg_t *elem = NULL; - intptr_t prot_str = (intptr_t) prot_strdup((char*) file); elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); elem->syscall = SCMP_SYS(open); elem->pindex = 0; elem->ptype = PARAM_PTR; - elem->param = prot_str; + elem->param = (intptr_t) prot_strdup((char*) file); elem->prot = 1; elem->next = filter_dynamic; filter_dynamic = elem; - // also allow openat + return 0; +} + +int +sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file) +{ + sandbox_cfg_t *elem = NULL; + elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); elem->syscall = SCMP_SYS(openat); elem->pindex = 1; elem->ptype = PARAM_PTR; - elem->param = prot_str; + elem->param = (intptr_t) prot_strdup((char*) file);; elem->prot = 1; elem->next = filter_dynamic; filter_dynamic = elem; diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 104d832bc1..dbf743e206 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -86,6 +86,7 @@ const char* sandbox_intern_string(const char *param); sandbox_cfg_t * sandbox_cfg_new(); int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file); +int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file); int sandbox_init(sandbox_cfg_t* cfg); #endif /* SANDBOX_H_ */ diff --git a/src/or/main.c b/src/or/main.c index d50f239e67..ab7b6ec1c7 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2644,8 +2644,9 @@ sandbox_init_filter() { sandbox_cfg_t *cfg = sandbox_cfg_new(); - sandbox_cfg_allow_open_filename(&cfg, + sandbox_cfg_allow_openat_filename(&cfg, get_datadir_fname("cached-status")); + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-certs")); sandbox_cfg_allow_open_filename(&cfg, From 5baea851892bcc2734c0e62e96b8d2d6e2626c51 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 30 Jul 2013 19:37:28 +0300 Subject: [PATCH 17/81] removed open flags (postponed), added mmap2 flags --- src/common/sandbox.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 8e7796bc5c..b55586b1ca 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -58,7 +58,13 @@ static sandbox_static_cfg_t filter_static[] = { {SCMP_SYS(socketcall), PARAM_NUM, 0, 18, 0}, #endif - {SCMP_SYS(open), PARAM_NUM, 1, O_RDONLY | O_CLOEXEC, 0} +#ifdef __NR_mmap2 + {SCMP_SYS(mmap2), PARAM_NUM, 2, PROT_READ, 0}, + {SCMP_SYS(mmap2), PARAM_NUM, 2, PROT_READ|PROT_WRITE, 0}, + {SCMP_SYS(mmap2), PARAM_NUM, 3, MAP_PRIVATE|MAP_ANONYMOUS, 0}, + {SCMP_SYS(mmap2), PARAM_NUM, 3, MAP_PRIVATE, 0}, +#endif + }; /** Variable used for storing all syscall numbers that will be allowed with the @@ -111,9 +117,6 @@ static int filter_nopar_gen[] = { SCMP_SYS(mkdir), SCMP_SYS(mlockall), SCMP_SYS(mmap), -#ifdef __NR_mmap2 - SCMP_SYS(mmap2), -#endif SCMP_SYS(mprotect), SCMP_SYS(mremap), SCMP_SYS(munmap), From 442f256f251d1a7a0c29c4d1254dda668f887d0c Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 30 Jul 2013 21:23:30 +0300 Subject: [PATCH 18/81] switched to a design using filters as function pointer arrays --- src/common/sandbox.c | 220 ++++++++++++++++++++++++++++--------------- src/common/sandbox.h | 3 + 2 files changed, 148 insertions(+), 75 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index b55586b1ca..28f23e8acf 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -18,6 +18,8 @@ #include "orconfig.h" #include "torint.h" +#define LENGHT(x) (sizeof(x)) / sizeof(x[0]) + #if defined(HAVE_SECCOMP_H) && defined(__linux__) #define USE_LIBSECCOMP #endif @@ -40,33 +42,6 @@ sandbox_cfg_t *filter_dynamic = NULL; -static sandbox_static_cfg_t filter_static[] = { - {SCMP_SYS(execve), PARAM_PTR, 0, (intptr_t)("/usr/local/bin/tor"), 0}, - {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGINT), 0}, - {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGTERM), 0}, - {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGPIPE), 0}, - {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGUSR1), 0}, - {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGUSR2), 0}, - {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGHUP), 0}, -#ifdef SIGXFSZ - {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGXFSZ), 0}, -#endif - {SCMP_SYS(rt_sigaction), PARAM_NUM, 0, (intptr_t)(SIGCHLD), 0}, - {SCMP_SYS(time), PARAM_NUM, 0, 0, 0}, - // accept4 workaround -#ifdef __NR_socketcall - {SCMP_SYS(socketcall), PARAM_NUM, 0, 18, 0}, -#endif - -#ifdef __NR_mmap2 - {SCMP_SYS(mmap2), PARAM_NUM, 2, PROT_READ, 0}, - {SCMP_SYS(mmap2), PARAM_NUM, 2, PROT_READ|PROT_WRITE, 0}, - {SCMP_SYS(mmap2), PARAM_NUM, 3, MAP_PRIVATE|MAP_ANONYMOUS, 0}, - {SCMP_SYS(mmap2), PARAM_NUM, 3, MAP_PRIVATE, 0}, -#endif - -}; - /** Variable used for storing all syscall numbers that will be allowed with the * stage 1 general Tor sandbox. */ @@ -159,28 +134,139 @@ static int filter_nopar_gen[] = { SCMP_SYS(unlink), }; +static int sb_rt_sigaction(scmp_filter_ctx ctx) { + int i, rc; + int param[] = { SIGINT, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGCHLD, +#ifdef SIGXFSZ + SIGXFSZ +#endif + }; + + for(i = 0; i < LENGHT(param); i++) { + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 1, + SCMP_CMP(0, SCMP_CMP_EQ, param[i])); + if(rc) + break; + } + + return rc; +} + +static int sb_execve(scmp_filter_ctx ctx) { + int rc; + sandbox_cfg_t *elem; + + // for each dynamic parameter filters + elem = filter_dynamic; + for (; elem != NULL; elem = elem->next) { + if (elem->prot == 1 && elem->syscall == SCMP_SYS(execve)) { + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), 1, + SCMP_CMP(0, SCMP_CMP_EQ, elem->param)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " + "error %d", rc); + return rc; + } + } + } + + return 0; +} + +static int sb_time(scmp_filter_ctx ctx) { + return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time), 1, + SCMP_CMP(0, SCMP_CMP_EQ, 0)); +} + +static int sb_accept4(scmp_filter_ctx ctx) { + return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 1, + SCMP_CMP(0, SCMP_CMP_EQ, 18)); +} + +#ifdef __NR_mmap2 +static int sb_mmap2(scmp_filter_ctx ctx) { + int rc = 0; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2, + SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ), + SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE)); + if(rc) { + return rc; + } + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2, + SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE), + SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS)); + if(rc) { + return rc; + } + + return 0; +} +#endif + +// TODO parameters +static int sb_open(scmp_filter_ctx ctx) { + int rc; + sandbox_cfg_t *elem; + + // for each dynamic parameter filters + elem = filter_dynamic; + for (; elem != NULL; elem = elem->next) { + if (elem->prot == 1 && elem->syscall == SCMP_SYS(open)) { + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, + SCMP_CMP(0, SCMP_CMP_EQ, elem->param)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " + "error %d", rc); + return rc; + } + } + } + + return 0; +} + +// TODO parameters +static int sb_openat(scmp_filter_ctx ctx) { + int rc; + sandbox_cfg_t *elem; + + // for each dynamic parameter filters + elem = filter_dynamic; + for (; elem != NULL; elem = elem->next) { + if (elem->prot == 1 && elem->syscall == SCMP_SYS(openat)) { + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 1, + SCMP_CMP(1, SCMP_CMP_EQ, elem->param)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " + "error %d", rc); + return rc; + } + } + } + + return 0; +} + +static sandbox_filter_func_t filter_func[] = { + sb_rt_sigaction, + sb_execve, + sb_time, + sb_accept4, + sb_mmap2, + sb_open, + sb_openat +}; + const char* sandbox_intern_string(const char *param) { - int i, filter_size; sandbox_cfg_t *elem; if (param == NULL) return NULL; - if (filter_static == NULL) { - filter_size = 0; - } else { - filter_size = sizeof(filter_static) / sizeof(filter_static[0]); - } - - for (i = 0; i < filter_size; i++) { - if (filter_static[i].prot && filter_static[i].ptype == PARAM_PTR - && !strncmp(param, (char*)(filter_static[i].param), MAX_PARAM_LEN)) { - return (char*)(filter_static[i].param); - } - } - for (elem = filter_dynamic; elem != NULL; elem = elem->next) { if (elem->prot && elem->ptype == PARAM_PTR && !strncmp(param, (char*)(elem->param), MAX_PARAM_LEN)) { @@ -264,46 +350,30 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file) static int add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) { - int i, filter_size, rc = 0; + int i, rc = 0; sandbox_cfg_t *elem; - if (filter_static != NULL) { - filter_size = sizeof(filter_static) / sizeof(filter_static[0]); - } else { - filter_size = 0; - } - - // for each dynamic parameter filters - elem = (cfg == NULL) ? filter_dynamic : cfg; - for (; elem != NULL; elem = elem->next) { - rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, elem->syscall, 1, - SCMP_CMP(elem->pindex, SCMP_CMP_EQ, elem->param)); - if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " - "error %d", rc); - return rc; - } - } - - // for each static parameter filter - for (i = 0; i < filter_size; i++) { - if (!filter_static[i].prot && filter_static[i].ptype == PARAM_PTR) { - filter_static[i].param = (intptr_t) prot_strdup( - (char*) (filter_static[i].param)); - } - - filter_static[i].prot = 1; - - rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, filter_static[i].syscall, 1, - SCMP_CMP(filter_static[i].pindex, SCMP_CMP_EQ, - filter_static[i].param)); - if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add syscall index %d, " - "received libseccomp error %d", i, rc); + // function pointer + for(i = 0; i < LENGHT(filter_func); i++) { + if ((filter_func[i])(ctx)) { + log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " + "error %d", rc); return rc; } } +// // for each dynamic parameter filters +// elem = (cfg == NULL) ? filter_dynamic : cfg; +// for (; elem != NULL; elem = elem->next) { +// rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, elem->syscall, 1, +// SCMP_CMP(elem->pindex, SCMP_CMP_EQ, elem->param)); +// if (rc != 0) { +// log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " +// "error %d", rc); +// return rc; +// } +// } + return 0; } diff --git a/src/common/sandbox.h b/src/common/sandbox.h index dbf743e206..4344134264 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -33,6 +33,7 @@ #define __USE_GNU #endif #include +#include #define MAX_PARAM_LEN 64 @@ -62,6 +63,8 @@ struct pfd_elem { }; typedef struct pfd_elem sandbox_cfg_t; +typedef int (*sandbox_filter_func_t)(scmp_filter_ctx ctx); + /** * Linux 32 bit definitions */ From c1f5f1842e4f51234e9f5fe0ba6597d75cd72f6b Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 30 Jul 2013 23:20:08 +0300 Subject: [PATCH 19/81] fully switched to function pointers; problems with socketcall parameters --- src/common/sandbox.c | 80 +++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 28f23e8acf..d13938dcc9 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -39,6 +39,7 @@ #include #include #include +#include sandbox_cfg_t *filter_dynamic = NULL; @@ -48,7 +49,6 @@ sandbox_cfg_t *filter_dynamic = NULL; static int filter_nopar_gen[] = { SCMP_SYS(access), SCMP_SYS(brk), - SCMP_SYS(clock_gettime), SCMP_SYS(close), SCMP_SYS(clone), SCMP_SYS(epoll_create), @@ -117,7 +117,6 @@ static int filter_nopar_gen[] = { SCMP_SYS(exit), // socket syscalls -// SCMP_SYS(accept4), SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname), @@ -128,13 +127,14 @@ static int filter_nopar_gen[] = { SCMP_SYS(sendto), SCMP_SYS(send), SCMP_SYS(setsockopt), - SCMP_SYS(socket), SCMP_SYS(socketpair), SCMP_SYS(recvfrom), SCMP_SYS(unlink), }; -static int sb_rt_sigaction(scmp_filter_ctx ctx) { +static int +sb_rt_sigaction(scmp_filter_ctx ctx) +{ int i, rc; int param[] = { SIGINT, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGCHLD, #ifdef SIGXFSZ @@ -152,7 +152,9 @@ static int sb_rt_sigaction(scmp_filter_ctx ctx) { return rc; } -static int sb_execve(scmp_filter_ctx ctx) { +static int +sb_execve(scmp_filter_ctx ctx) +{ int rc; sandbox_cfg_t *elem; @@ -173,18 +175,24 @@ static int sb_execve(scmp_filter_ctx ctx) { return 0; } -static int sb_time(scmp_filter_ctx ctx) { +static int +sb_time(scmp_filter_ctx ctx) +{ return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time), 1, SCMP_CMP(0, SCMP_CMP_EQ, 0)); } -static int sb_accept4(scmp_filter_ctx ctx) { +static int +sb_accept4(scmp_filter_ctx ctx) +{ return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 1, SCMP_CMP(0, SCMP_CMP_EQ, 18)); } #ifdef __NR_mmap2 -static int sb_mmap2(scmp_filter_ctx ctx) { +static int +sb_mmap2(scmp_filter_ctx ctx) +{ int rc = 0; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2, @@ -206,7 +214,9 @@ static int sb_mmap2(scmp_filter_ctx ctx) { #endif // TODO parameters -static int sb_open(scmp_filter_ctx ctx) { +static int +sb_open(scmp_filter_ctx ctx) +{ int rc; sandbox_cfg_t *elem; @@ -228,7 +238,9 @@ static int sb_open(scmp_filter_ctx ctx) { } // TODO parameters -static int sb_openat(scmp_filter_ctx ctx) { +static int +sb_openat(scmp_filter_ctx ctx) +{ int rc; sandbox_cfg_t *elem; @@ -249,6 +261,38 @@ static int sb_openat(scmp_filter_ctx ctx) { return 0; } +static int +sb_clock_gettime(scmp_filter_ctx ctx) +{ + return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clock_gettime), 1, + SCMP_CMP(0, SCMP_CMP_EQ, CLOCK_MONOTONIC)); +} + +// TODO: param not working +static int +sb_socket(scmp_filter_ctx ctx) +{ + int rc = 0; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 4, + SCMP_CMP(0, SCMP_CMP_EQ, 1), + SCMP_CMP(1, SCMP_CMP_EQ, PF_INET), + SCMP_CMP(2, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC), + SCMP_CMP(3, SCMP_CMP_EQ, IPPROTO_TCP)); + if (rc) + return rc; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 4, + SCMP_CMP(0, SCMP_CMP_EQ, 1), + SCMP_CMP(1, SCMP_CMP_EQ, PF_NETLINK), + SCMP_CMP(2, SCMP_CMP_EQ, SOCK_RAW), + SCMP_CMP(3, SCMP_CMP_EQ, 0)); + if (rc) + return rc; + + return 0; +} + static sandbox_filter_func_t filter_func[] = { sb_rt_sigaction, sb_execve, @@ -256,7 +300,8 @@ static sandbox_filter_func_t filter_func[] = { sb_accept4, sb_mmap2, sb_open, - sb_openat + sb_openat, + sb_clock_gettime, }; const char* @@ -351,7 +396,6 @@ static int add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) { int i, rc = 0; - sandbox_cfg_t *elem; // function pointer for(i = 0; i < LENGHT(filter_func); i++) { @@ -362,18 +406,6 @@ add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) } } -// // for each dynamic parameter filters -// elem = (cfg == NULL) ? filter_dynamic : cfg; -// for (; elem != NULL; elem = elem->next) { -// rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, elem->syscall, 1, -// SCMP_CMP(elem->pindex, SCMP_CMP_EQ, elem->param)); -// if (rc != 0) { -// log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " -// "error %d", rc); -// return rc; -// } -// } - return 0; } From 686cf4c0fffa5af63bf989eb53af9a962692670a Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 30 Jul 2013 23:43:42 +0300 Subject: [PATCH 20/81] clean stable version --- src/common/sandbox.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index d13938dcc9..8a31ce0078 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -127,6 +127,7 @@ static int filter_nopar_gen[] = { SCMP_SYS(sendto), SCMP_SYS(send), SCMP_SYS(setsockopt), + SCMP_SYS(socket), SCMP_SYS(socketpair), SCMP_SYS(recvfrom), SCMP_SYS(unlink), @@ -142,10 +143,10 @@ sb_rt_sigaction(scmp_filter_ctx ctx) #endif }; - for(i = 0; i < LENGHT(param); i++) { + for (i = 0; i < LENGHT(param); i++) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 1, SCMP_CMP(0, SCMP_CMP_EQ, param[i])); - if(rc) + if (rc) break; } @@ -198,14 +199,14 @@ sb_mmap2(scmp_filter_ctx ctx) rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2, SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ), SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE)); - if(rc) { + if (rc) { return rc; } rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2, SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE), SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS)); - if(rc) { + if (rc) { return rc; } @@ -398,7 +399,7 @@ add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) int i, rc = 0; // function pointer - for(i = 0; i < LENGHT(filter_func); i++) { + for (i = 0; i < LENGHT(filter_func); i++) { if ((filter_func[i])(ctx)) { log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " "error %d", rc); @@ -576,7 +577,8 @@ initialise_libseccomp_sandbox(sandbox_cfg_t* cfg) #endif // USE_LIBSECCOMP sandbox_cfg_t* -sandbox_cfg_new() { +sandbox_cfg_new() +{ return NULL; } From 5fc0e13db821b76c2bdee06c8622a95383d1b915 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 30 Jul 2013 23:52:54 +0300 Subject: [PATCH 21/81] fcntl64 --- src/common/sandbox.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 8a31ce0078..acf3038145 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -55,11 +55,7 @@ static int filter_nopar_gen[] = { SCMP_SYS(epoll_ctl), SCMP_SYS(epoll_wait), SCMP_SYS(fcntl), -#ifdef __NR_fcntl64 - /* Older libseccomp versions don't define PNR entries for all of these, - * so we need to ifdef them here.*/ - SCMP_SYS(fcntl64), -#endif + SCMP_SYS(flock), SCMP_SYS(fstat), #ifdef __NR_fstat64 @@ -294,6 +290,42 @@ sb_socket(scmp_filter_ctx ctx) return 0; } +// TODO: param not working +static int +sb_setsockopt(scmp_filter_ctx ctx) +{ + int rc = 0; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 2, + SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET), + SCMP_CMP(2, SCMP_CMP_EQ, SO_REUSEADDR)); + if (rc) + return rc; + + return 0; +} + +#ifdef __NR_fcntl64 +static int +sb_fcntl64(scmp_filter_ctx ctx) +{ + int rc = 0; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 1, + SCMP_CMP(1, SCMP_CMP_EQ, F_GETFL)); + if (rc) + return rc; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 2, + SCMP_CMP(1, SCMP_CMP_EQ, F_SETFL), + SCMP_CMP(2, SCMP_CMP_EQ, O_RDWR|O_NONBLOCK)); + if (rc) + return rc; + + return 0; +} +#endif + static sandbox_filter_func_t filter_func[] = { sb_rt_sigaction, sb_execve, @@ -303,6 +335,7 @@ static sandbox_filter_func_t filter_func[] = { sb_open, sb_openat, sb_clock_gettime, + sb_fcntl64 }; const char* From f0840ed4c9f17f199d73b8b9788b08af0265026d Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 31 Jul 2013 00:27:14 +0300 Subject: [PATCH 22/81] epoll_ctl --- src/common/sandbox.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index acf3038145..6de95da4dc 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -52,7 +53,6 @@ static int filter_nopar_gen[] = { SCMP_SYS(close), SCMP_SYS(clone), SCMP_SYS(epoll_create), - SCMP_SYS(epoll_ctl), SCMP_SYS(epoll_wait), SCMP_SYS(fcntl), @@ -326,6 +326,24 @@ sb_fcntl64(scmp_filter_ctx ctx) } #endif +static int +sb_epoll_ctl(scmp_filter_ctx ctx) +{ + int rc = 0; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 1, + SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_ADD)); + if (rc) + return rc; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 1, + SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_MOD)); + if (rc) + return rc; + + return 0; +} + static sandbox_filter_func_t filter_func[] = { sb_rt_sigaction, sb_execve, @@ -335,7 +353,8 @@ static sandbox_filter_func_t filter_func[] = { sb_open, sb_openat, sb_clock_gettime, - sb_fcntl64 + sb_fcntl64, + sb_epoll_ctl }; const char* From 313cbe6e24618c4c5875c8e3aab4cd563c97791f Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 31 Jul 2013 11:35:25 +0300 Subject: [PATCH 23/81] sigprocmask, epoll_ctl, prctl, mprotect, flock, futex, mremap --- src/common/sandbox.c | 115 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 8 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 6de95da4dc..fe2f457b03 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include @@ -55,13 +57,10 @@ static int filter_nopar_gen[] = { SCMP_SYS(epoll_create), SCMP_SYS(epoll_wait), SCMP_SYS(fcntl), - - SCMP_SYS(flock), SCMP_SYS(fstat), #ifdef __NR_fstat64 SCMP_SYS(fstat64), #endif - SCMP_SYS(futex), SCMP_SYS(getdents64), SCMP_SYS(getegid), #ifdef __NR_getegid32 @@ -88,14 +87,10 @@ static int filter_nopar_gen[] = { SCMP_SYS(mkdir), SCMP_SYS(mlockall), SCMP_SYS(mmap), - SCMP_SYS(mprotect), - SCMP_SYS(mremap), SCMP_SYS(munmap), SCMP_SYS(poll), - SCMP_SYS(prctl), SCMP_SYS(read), SCMP_SYS(rename), - SCMP_SYS(rt_sigprocmask), SCMP_SYS(rt_sigreturn), #ifdef __NR_sigreturn SCMP_SYS(sigreturn), @@ -344,8 +339,107 @@ sb_epoll_ctl(scmp_filter_ctx ctx) return 0; } +/** + * If multiple filters need to be added, seccomp needs to be whitelisted in + * this list. + */ +static int +sb_prctl(scmp_filter_ctx ctx) +{ + int rc = 0; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 1, + SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE)); + if (rc) + return rc; + + return 0; +} + +/** + * does not NEED tobe here.. only occurs before filter + */ +static int +sb_mprotect(scmp_filter_ctx ctx) +{ + int rc = 0; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 1, + SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ)); + if (rc) + return rc; + + return 0; +} + +/** + * does not NEED tobe here.. only occurs before filter + */ +static int +sb_rt_sigprocmask(scmp_filter_ctx ctx) +{ + int rc = 0; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 1, + SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK)); + if (rc) + return rc; + + return 0; +} + +/** + * does not NEED tobe here.. only occurs before filter + */ +static int +sb_flock(scmp_filter_ctx ctx) +{ + int rc = 0; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock), 1, + SCMP_CMP(1, SCMP_CMP_EQ, LOCK_EX|LOCK_NB)); + if (rc) + return rc; + + return 0; +} + +/** + * does not NEED tobe here.. only occurs before filter + */ +static int +sb_futex(scmp_filter_ctx ctx) +{ + int rc = 0; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 1, + SCMP_CMP(1, SCMP_CMP_EQ, + FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME)); + if (rc) + return rc; + + return 0; +} + +/** + * does not NEED tobe here.. only occurs before filter + */ +static int +sb_mremap(scmp_filter_ctx ctx) +{ + int rc = 0; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap), 1, + SCMP_CMP(1, SCMP_CMP_EQ, MREMAP_MAYMOVE)); + if (rc) + return rc; + + return 0; +} + static sandbox_filter_func_t filter_func[] = { sb_rt_sigaction, + sb_rt_sigprocmask, sb_execve, sb_time, sb_accept4, @@ -354,7 +448,12 @@ static sandbox_filter_func_t filter_func[] = { sb_openat, sb_clock_gettime, sb_fcntl64, - sb_epoll_ctl + sb_epoll_ctl, + sb_prctl, + sb_mprotect, + sb_flock, + sb_futex, + sb_mremap }; const char* From dde3ed385bc9de8bffa52b9b5e525fb7a0aae88b Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 31 Jul 2013 12:05:10 +0300 Subject: [PATCH 24/81] removed access, set_robust_list, set_thread_area, set_tid_address, uname; added sb_poll --- src/common/sandbox.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index fe2f457b03..d330cab98e 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -43,6 +43,7 @@ #include #include #include +#include sandbox_cfg_t *filter_dynamic = NULL; @@ -50,7 +51,6 @@ sandbox_cfg_t *filter_dynamic = NULL; * stage 1 general Tor sandbox. */ static int filter_nopar_gen[] = { - SCMP_SYS(access), SCMP_SYS(brk), SCMP_SYS(close), SCMP_SYS(clone), @@ -88,25 +88,27 @@ static int filter_nopar_gen[] = { SCMP_SYS(mlockall), SCMP_SYS(mmap), SCMP_SYS(munmap), - SCMP_SYS(poll), SCMP_SYS(read), SCMP_SYS(rename), SCMP_SYS(rt_sigreturn), #ifdef __NR_sigreturn SCMP_SYS(sigreturn), #endif - SCMP_SYS(set_robust_list), - SCMP_SYS(set_thread_area), - SCMP_SYS(set_tid_address), SCMP_SYS(stat), #ifdef __NR_stat64 SCMP_SYS(stat64), #endif - SCMP_SYS(uname), SCMP_SYS(write), SCMP_SYS(exit_group), SCMP_SYS(exit), + // Not needed.. +// SCMP_SYS(access), +// SCMP_SYS(set_robust_list), +// SCMP_SYS(set_thread_area), +// SCMP_SYS(set_tid_address), +// SCMP_SYS(uname), + // socket syscalls SCMP_SYS(bind), SCMP_SYS(connect), @@ -437,6 +439,20 @@ sb_mremap(scmp_filter_ctx ctx) return 0; } +static int +sb_poll(scmp_filter_ctx ctx) +{ + int rc = 0; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(poll), 2, + SCMP_CMP(1, SCMP_CMP_EQ, 1), + SCMP_CMP(2, SCMP_CMP_EQ, 10)); + if (rc) + return rc; + + return 0; +} + static sandbox_filter_func_t filter_func[] = { sb_rt_sigaction, sb_rt_sigprocmask, @@ -453,7 +469,8 @@ static sandbox_filter_func_t filter_func[] = { sb_mprotect, sb_flock, sb_futex, - sb_mremap + sb_mremap, + sb_poll }; const char* From d897690fc7f6f6b5b3d37da2e3e2b05f38222f06 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 5 Aug 2013 14:17:46 +0300 Subject: [PATCH 25/81] fixes suggested by nickm --- src/common/sandbox.c | 32 +++++++++++++++++++++++++++----- src/common/util.h | 2 ++ src/or/main.c | 1 + 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index d330cab98e..e35f51f052 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -17,8 +17,7 @@ #include "torlog.h" #include "orconfig.h" #include "torint.h" - -#define LENGHT(x) (sizeof(x)) / sizeof(x[0]) +#include "util.h" #if defined(HAVE_SECCOMP_H) && defined(__linux__) #define USE_LIBSECCOMP @@ -45,7 +44,7 @@ #include #include -sandbox_cfg_t *filter_dynamic = NULL; +static sandbox_cfg_t *filter_dynamic = NULL; /** Variable used for storing all syscall numbers that will be allowed with the * stage 1 general Tor sandbox. @@ -136,7 +135,7 @@ sb_rt_sigaction(scmp_filter_ctx ctx) #endif }; - for (i = 0; i < LENGHT(param); i++) { + for (i = 0; i < ARRAY_LENGTH(param); i++) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 1, SCMP_CMP(0, SCMP_CMP_EQ, param[i])); if (rc) @@ -323,6 +322,7 @@ sb_fcntl64(scmp_filter_ctx ctx) } #endif +// allows everything but will keep for now.. static int sb_epoll_ctl(scmp_filter_ctx ctx) { @@ -338,6 +338,11 @@ sb_epoll_ctl(scmp_filter_ctx ctx) if (rc) return rc; + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 1, + SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_DEL)); + if (rc) + return rc; + return 0; } @@ -561,13 +566,30 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file) return 0; } +int +sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com) +{ + sandbox_cfg_t *elem = NULL; + + elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); + elem->syscall = SCMP_SYS(openat); + elem->pindex = 1; + elem->ptype = PARAM_PTR; + elem->param = (intptr_t) prot_strdup((char*) com);; + elem->prot = 1; + elem->next = filter_dynamic; + filter_dynamic = elem; + + return 0; +} + static int add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) { int i, rc = 0; // function pointer - for (i = 0; i < LENGHT(filter_func); i++) { + for (i = 0; i < ARRAY_LENGTH(filter_func); i++) { if ((filter_func[i])(ctx)) { log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " "error %d", rc); diff --git a/src/common/util.h b/src/common/util.h index 5596378bca..fc4ca291b0 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -533,5 +533,7 @@ int format_helper_exit_status(unsigned char child_state, const char *libor_get_digests(void); +#define ARRAY_LENGTH(x) (sizeof(x)) / sizeof(x[0]) + #endif diff --git a/src/or/main.c b/src/or/main.c index ab7b6ec1c7..ab3b8405e4 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2644,6 +2644,7 @@ sandbox_init_filter() { sandbox_cfg_t *cfg = sandbox_cfg_new(); + // TODO: mem leak sandbox_cfg_allow_openat_filename(&cfg, get_datadir_fname("cached-status")); From 356b646976b80c0ca1d582227d625130e7e76755 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 5 Aug 2013 15:40:23 +0300 Subject: [PATCH 26/81] added execve and multi-configuration support --- src/common/sandbox.c | 101 +++++++++++++++++++++++++------------------ src/common/sandbox.h | 4 +- src/or/main.c | 4 ++ 3 files changed, 67 insertions(+), 42 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index e35f51f052..ed7fe3b319 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -126,7 +126,7 @@ static int filter_nopar_gen[] = { }; static int -sb_rt_sigaction(scmp_filter_ctx ctx) +sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int i, rc; int param[] = { SIGINT, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGCHLD, @@ -146,19 +146,18 @@ sb_rt_sigaction(scmp_filter_ctx ctx) } static int -sb_execve(scmp_filter_ctx ctx) +sb_execve(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; - sandbox_cfg_t *elem; + sandbox_cfg_t *elem = NULL; // for each dynamic parameter filters - elem = filter_dynamic; - for (; elem != NULL; elem = elem->next) { + for (elem = filter; elem != NULL; elem = elem->next) { if (elem->prot == 1 && elem->syscall == SCMP_SYS(execve)) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), 1, SCMP_CMP(0, SCMP_CMP_EQ, elem->param)); if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " + log_err(LD_BUG,"(Sandbox) failed to add execve syscall, received libseccomp " "error %d", rc); return rc; } @@ -169,14 +168,14 @@ sb_execve(scmp_filter_ctx ctx) } static int -sb_time(scmp_filter_ctx ctx) +sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time), 1, SCMP_CMP(0, SCMP_CMP_EQ, 0)); } static int -sb_accept4(scmp_filter_ctx ctx) +sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 1, SCMP_CMP(0, SCMP_CMP_EQ, 18)); @@ -184,7 +183,7 @@ sb_accept4(scmp_filter_ctx ctx) #ifdef __NR_mmap2 static int -sb_mmap2(scmp_filter_ctx ctx) +sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; @@ -208,19 +207,18 @@ sb_mmap2(scmp_filter_ctx ctx) // TODO parameters static int -sb_open(scmp_filter_ctx ctx) +sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; - sandbox_cfg_t *elem; + sandbox_cfg_t *elem = NULL; // for each dynamic parameter filters - elem = filter_dynamic; - for (; elem != NULL; elem = elem->next) { + for (elem = filter; elem != NULL; elem = elem->next) { if (elem->prot == 1 && elem->syscall == SCMP_SYS(open)) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, SCMP_CMP(0, SCMP_CMP_EQ, elem->param)); if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " + log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " "error %d", rc); return rc; } @@ -232,19 +230,18 @@ sb_open(scmp_filter_ctx ctx) // TODO parameters static int -sb_openat(scmp_filter_ctx ctx) +sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc; - sandbox_cfg_t *elem; + sandbox_cfg_t *elem = NULL; // for each dynamic parameter filters - elem = filter_dynamic; - for (; elem != NULL; elem = elem->next) { + for (elem = filter; elem != NULL; elem = elem->next) { if (elem->prot == 1 && elem->syscall == SCMP_SYS(openat)) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 1, SCMP_CMP(1, SCMP_CMP_EQ, elem->param)); if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " + log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received libseccomp " "error %d", rc); return rc; } @@ -255,7 +252,7 @@ sb_openat(scmp_filter_ctx ctx) } static int -sb_clock_gettime(scmp_filter_ctx ctx) +sb_clock_gettime(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clock_gettime), 1, SCMP_CMP(0, SCMP_CMP_EQ, CLOCK_MONOTONIC)); @@ -263,7 +260,7 @@ sb_clock_gettime(scmp_filter_ctx ctx) // TODO: param not working static int -sb_socket(scmp_filter_ctx ctx) +sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; @@ -288,7 +285,7 @@ sb_socket(scmp_filter_ctx ctx) // TODO: param not working static int -sb_setsockopt(scmp_filter_ctx ctx) +sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; @@ -303,7 +300,7 @@ sb_setsockopt(scmp_filter_ctx ctx) #ifdef __NR_fcntl64 static int -sb_fcntl64(scmp_filter_ctx ctx) +sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; @@ -324,7 +321,7 @@ sb_fcntl64(scmp_filter_ctx ctx) // allows everything but will keep for now.. static int -sb_epoll_ctl(scmp_filter_ctx ctx) +sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; @@ -351,7 +348,7 @@ sb_epoll_ctl(scmp_filter_ctx ctx) * this list. */ static int -sb_prctl(scmp_filter_ctx ctx) +sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; @@ -367,7 +364,7 @@ sb_prctl(scmp_filter_ctx ctx) * does not NEED tobe here.. only occurs before filter */ static int -sb_mprotect(scmp_filter_ctx ctx) +sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; @@ -383,7 +380,7 @@ sb_mprotect(scmp_filter_ctx ctx) * does not NEED tobe here.. only occurs before filter */ static int -sb_rt_sigprocmask(scmp_filter_ctx ctx) +sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; @@ -399,7 +396,7 @@ sb_rt_sigprocmask(scmp_filter_ctx ctx) * does not NEED tobe here.. only occurs before filter */ static int -sb_flock(scmp_filter_ctx ctx) +sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; @@ -415,7 +412,7 @@ sb_flock(scmp_filter_ctx ctx) * does not NEED tobe here.. only occurs before filter */ static int -sb_futex(scmp_filter_ctx ctx) +sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; @@ -432,12 +429,12 @@ sb_futex(scmp_filter_ctx ctx) * does not NEED tobe here.. only occurs before filter */ static int -sb_mremap(scmp_filter_ctx ctx) +sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap), 1, - SCMP_CMP(1, SCMP_CMP_EQ, MREMAP_MAYMOVE)); + SCMP_CMP(3, SCMP_CMP_EQ, MREMAP_MAYMOVE)); if (rc) return rc; @@ -445,7 +442,7 @@ sb_mremap(scmp_filter_ctx ctx) } static int -sb_poll(scmp_filter_ctx ctx) +sb_poll(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; @@ -543,8 +540,9 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) elem->ptype = PARAM_PTR; elem->param = (intptr_t) prot_strdup((char*) file); elem->prot = 1; - elem->next = filter_dynamic; - filter_dynamic = elem; + + elem->next = *cfg; + *cfg = elem; return 0; } @@ -560,8 +558,9 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file) elem->ptype = PARAM_PTR; elem->param = (intptr_t) prot_strdup((char*) file);; elem->prot = 1; - elem->next = filter_dynamic; - filter_dynamic = elem; + + elem->next = *cfg; + *cfg = elem; return 0; } @@ -577,8 +576,9 @@ sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com) elem->ptype = PARAM_PTR; elem->param = (intptr_t) prot_strdup((char*) com);; elem->prot = 1; - elem->next = filter_dynamic; - filter_dynamic = elem; + + elem->next = *cfg; + *cfg = elem; return 0; } @@ -590,9 +590,9 @@ add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) // function pointer for (i = 0; i < ARRAY_LENGTH(filter_func); i++) { - if ((filter_func[i])(ctx)) { - log_err(LD_BUG,"(Sandbox) failed to add syscall, received libseccomp " - "error %d", rc); + if ((filter_func[i])(ctx, cfg)) { + log_err(LD_BUG,"(Sandbox) failed to add syscall %d, received libseccomp " + "error %d", i, rc); return rc; } } @@ -745,6 +745,22 @@ install_sigsys_debugging(void) return 0; } + +static int register_cfg(sandbox_cfg_t* cfg) { + sandbox_cfg_t *elem = NULL; + + if (filter_dynamic == NULL) { + filter_dynamic = cfg; + return 0; + } + + for (elem = filter_dynamic; elem->next != NULL; elem = elem->next); + + elem->next = cfg; + + return 0; +} + #endif // USE_LIBSECCOMP #ifdef USE_LIBSECCOMP @@ -761,6 +777,9 @@ initialise_libseccomp_sandbox(sandbox_cfg_t* cfg) if (install_syscall_filter(cfg)) return -2; + if (register_cfg(cfg)) + return -3; + return 0; } diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 4344134264..1d5c8236e1 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -63,7 +63,8 @@ struct pfd_elem { }; typedef struct pfd_elem sandbox_cfg_t; -typedef int (*sandbox_filter_func_t)(scmp_filter_ctx ctx); +typedef int (*sandbox_filter_func_t)(scmp_filter_ctx ctx, + sandbox_cfg_t *filter); /** * Linux 32 bit definitions @@ -90,6 +91,7 @@ const char* sandbox_intern_string(const char *param); sandbox_cfg_t * sandbox_cfg_new(); int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file); int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file); +int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com); int sandbox_init(sandbox_cfg_t* cfg); #endif /* SANDBOX_H_ */ diff --git a/src/or/main.c b/src/or/main.c index ab3b8405e4..3c9824677a 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2650,6 +2650,8 @@ sandbox_init_filter() sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-certs")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname("cached-certs.tmp")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-consensus")); sandbox_cfg_allow_open_filename(&cfg, @@ -2681,6 +2683,8 @@ sandbox_init_filter() sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("unparseable-desc")); + sandbox_cfg_allow_execve(&cfg, "/usr/local/bin/tor"); + return cfg; } From a960e56c6818a2b1ae0173a0c6439a0c0f68d969 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 5 Aug 2013 16:01:31 +0300 Subject: [PATCH 27/81] multi-configuration support using sandbox_t struct --- src/common/sandbox.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 1d5c8236e1..2b265443f8 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -66,6 +66,15 @@ typedef struct pfd_elem sandbox_cfg_t; typedef int (*sandbox_filter_func_t)(scmp_filter_ctx ctx, sandbox_cfg_t *filter); + +typedef struct { + // function pointers associated with filter + sandbox_filter_func_t *filter_func; + + // filter function pointer parameters + sandbox_cfg_t *filter_dynamic; +} sandbox_t; + /** * Linux 32 bit definitions */ From b3a8c08a9217effb0065b9bc5769f18e120ca4d1 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 7 Aug 2013 13:13:12 +0300 Subject: [PATCH 28/81] orport progress (not functional), nickm suggested fixes --- src/common/sandbox.c | 100 +++++++++++++++++++++++++++++++++++-------- src/or/cpuworker.c | 2 + src/or/main.c | 49 +++++++++++++-------- 3 files changed, 116 insertions(+), 35 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index ed7fe3b319..1f15674557 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -50,6 +50,7 @@ static sandbox_cfg_t *filter_dynamic = NULL; * stage 1 general Tor sandbox. */ static int filter_nopar_gen[] = { + SCMP_SYS(access), SCMP_SYS(brk), SCMP_SYS(close), SCMP_SYS(clone), @@ -90,23 +91,22 @@ static int filter_nopar_gen[] = { SCMP_SYS(read), SCMP_SYS(rename), SCMP_SYS(rt_sigreturn), + SCMP_SYS(set_robust_list), #ifdef __NR_sigreturn SCMP_SYS(sigreturn), #endif SCMP_SYS(stat), #ifdef __NR_stat64 - SCMP_SYS(stat64), + SCMP_SYS(stat64), // TODO #endif + SCMP_SYS(uname), SCMP_SYS(write), SCMP_SYS(exit_group), SCMP_SYS(exit), // Not needed.. -// SCMP_SYS(access), -// SCMP_SYS(set_robust_list), // SCMP_SYS(set_thread_area), // SCMP_SYS(set_tid_address), -// SCMP_SYS(uname), // socket syscalls SCMP_SYS(bind), @@ -201,6 +201,34 @@ sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return rc; } + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2, + SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE), + SCMP_CMP(3, SCMP_CMP_EQ,MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK)); + if (rc) { + return rc; + } + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2, + SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE), + SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE)); + if (rc) { + return rc; + } + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2, + SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE), + SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS)); + if (rc) { + return rc; + } + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2, + SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_EXEC), + SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_DENYWRITE)); + if (rc) { + return rc; + } + return 0; } #endif @@ -225,6 +253,24 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } } + // todo remove when libevent fix + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, + SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " + "error %d", rc); + return rc; + } + + // problem: required by getaddrinfo + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, + SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY|O_CLOEXEC)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " + "error %d", rc); + return rc; + } + return 0; } @@ -315,6 +361,17 @@ sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (rc) return rc; + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 1, + SCMP_CMP(1, SCMP_CMP_EQ, F_GETFD)); + if (rc) + return rc; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 2, + SCMP_CMP(1, SCMP_CMP_EQ, F_SETFD), + SCMP_CMP(2, SCMP_CMP_EQ, FD_CLOEXEC)); + if (rc) + return rc; + return 0; } #endif @@ -373,12 +430,14 @@ sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (rc) return rc; + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 1, + SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE)); + if (rc) + return rc; + return 0; } -/** - * does not NEED tobe here.. only occurs before filter - */ static int sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -389,6 +448,11 @@ sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (rc) return rc; + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 1, + SCMP_CMP(0, SCMP_CMP_EQ, SIG_SETMASK)); + if (rc) + return rc; + return 0; } @@ -408,20 +472,28 @@ sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } -/** - * does not NEED tobe here.. only occurs before filter - */ static int sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + // can remove rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 1, SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME)); if (rc) return rc; + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 1, + SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAKE_PRIVATE)); + if (rc) + return rc; + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 1, + SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_PRIVATE)); + if (rc) + return rc; + return 0; } @@ -605,14 +677,8 @@ add_noparam_filter(scmp_filter_ctx ctx) { int i, filter_size, rc = 0; - if (filter_nopar_gen != NULL) { - filter_size = sizeof(filter_nopar_gen) / sizeof(filter_nopar_gen[0]); - } else { - filter_size = 0; - } - // add general filters - for (i = 0; i < filter_size; i++) { + for (i = 0; i < ARRAY_LENGTH(filter_nopar_gen); i++) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i], 0); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add syscall index %d, " diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index 61f9faa394..245f67e56a 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -571,6 +571,8 @@ spawn_enough_cpuworkers(void) if (num_cpuworkers_needed > MAX_CPUWORKERS) num_cpuworkers_needed = MAX_CPUWORKERS; + getchar(); + while (num_cpuworkers < num_cpuworkers_needed) { if (spawn_cpuworker() < 0) { log_warn(LD_GENERAL,"Cpuworker spawn failed. Will try again later."); diff --git a/src/or/main.c b/src/or/main.c index 3c9824677a..5b6b778ef5 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2645,23 +2645,18 @@ sandbox_init_filter() sandbox_cfg_t *cfg = sandbox_cfg_new(); // TODO: mem leak - sandbox_cfg_allow_openat_filename(&cfg, - get_datadir_fname("cached-status")); + sandbox_cfg_allow_openat_filename(&cfg, get_datadir_fname("cached-status")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-certs")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-certs.tmp")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-consensus")); + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-certs")); + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-certs.tmp")); + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-consensus")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("unverified-consensus")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-microdesc-consensus")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-microdesc-consensus.tmp")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-microdescs")); + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-microdescs")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-microdescs.tmp")); sandbox_cfg_allow_open_filename(&cfg, @@ -2670,18 +2665,36 @@ sandbox_init_filter() get_datadir_fname("cached-microdescs.new.tmp")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("unverified-microdesc-consensus")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-descriptors")); + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-descriptors")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-descriptors.new")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-extrainfo")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("state.tmp")); + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-extrainfo")); + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("state.tmp")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("unparseable-desc.tmp")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("unparseable-desc")); + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("unparseable-desc")); + + // orport + if (server_mode(get_options())) { + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname2("keys", "secret_id_key")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname2("keys", "secret_onion_key")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname2("keys", "secret_onion_key_ntor")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname2("keys", "secret_id_key.old")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname2("keys", "secret_onion_key.old")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname2("keys", "secret_onion_key_ntor.old")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname2("keys", "secret_onion_key.tmp")); + + sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("fingerprint")); + + sandbox_cfg_allow_open_filename(&cfg, "/etc/resolv.conf"); + } sandbox_cfg_allow_execve(&cfg, "/usr/local/bin/tor"); From 89b39db003922f5b05f9e4e2fc7658b225a2f70a Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Fri, 9 Aug 2013 19:07:20 +0300 Subject: [PATCH 29/81] updated filters to work with orport --- src/common/crypto.c | 3 ++- src/common/sandbox.c | 16 +++++++++++++++- src/or/cpuworker.c | 2 -- src/or/main.c | 19 ++++++++++++++++++- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/common/crypto.c b/src/common/crypto.c index e60172b744..71d5166831 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -56,6 +56,7 @@ #include "../common/util.h" #include "container.h" #include "compat.h" +#include "sandbox.h" #if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8) #error "We require OpenSSL >= 0.9.8" @@ -2349,7 +2350,7 @@ crypto_strongest_rand(uint8_t *out, size_t out_len) return 0; #else for (i = 0; filenames[i]; ++i) { - fd = open(filenames[i], O_RDONLY, 0); + fd = open(sandbox_intern_string(filenames[i]), O_RDONLY, 0); if (fd<0) continue; log_info(LD_CRYPTO, "Reading entropy from \"%s\"", filenames[i]); n = read_all(fd, (char*)out, out_len, 0); diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 1f15674557..2ba1432cf7 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -104,6 +104,8 @@ static int filter_nopar_gen[] = { SCMP_SYS(exit_group), SCMP_SYS(exit), + SCMP_SYS(madvise), + // Not needed.. // SCMP_SYS(set_thread_area), // SCMP_SYS(set_tid_address), @@ -194,6 +196,13 @@ sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return rc; } + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2, + SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE), + SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE)); + if (rc) { + return rc; + } + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 2, SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE), SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS)); @@ -430,6 +439,11 @@ sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (rc) return rc; + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 1, + SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); + if (rc) + return rc; + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 1, SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE)); if (rc) @@ -675,7 +689,7 @@ add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) static int add_noparam_filter(scmp_filter_ctx ctx) { - int i, filter_size, rc = 0; + int i, rc = 0; // add general filters for (i = 0; i < ARRAY_LENGTH(filter_nopar_gen); i++) { diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index 245f67e56a..61f9faa394 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -571,8 +571,6 @@ spawn_enough_cpuworkers(void) if (num_cpuworkers_needed > MAX_CPUWORKERS) num_cpuworkers_needed = MAX_CPUWORKERS; - getchar(); - while (num_cpuworkers < num_cpuworkers_needed) { if (spawn_cpuworker() < 0) { log_warn(LD_GENERAL,"Cpuworker spawn failed. Will try again later."); diff --git a/src/or/main.c b/src/or/main.c index 5b6b778ef5..36acde431a 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2665,9 +2665,16 @@ sandbox_init_filter() get_datadir_fname("cached-microdescs.new.tmp")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("unverified-microdesc-consensus")); - sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-descriptors")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname("cached-descriptors")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-descriptors.new")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname("cached-descriptors.tmp")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname("cached-descriptors.new.tmp")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname("cached-descriptors.tmp.tmp")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-extrainfo")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("state.tmp")); sandbox_cfg_allow_open_filename(&cfg, @@ -2682,6 +2689,8 @@ sandbox_init_filter() get_datadir_fname2("keys", "secret_onion_key")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname2("keys", "secret_onion_key_ntor")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname2("keys", "secret_onion_key_ntor.tmp")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname2("keys", "secret_id_key.old")); sandbox_cfg_allow_open_filename(&cfg, @@ -2692,8 +2701,16 @@ sandbox_init_filter() get_datadir_fname2("keys", "secret_onion_key.tmp")); sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("fingerprint")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname("cached-consensus.tmp")); + sandbox_cfg_allow_open_filename(&cfg, + get_datadir_fname("cached-consensus")); sandbox_cfg_allow_open_filename(&cfg, "/etc/resolv.conf"); + sandbox_cfg_allow_open_filename(&cfg, "/dev/srandom"); + sandbox_cfg_allow_open_filename(&cfg, "/dev/urandom"); + sandbox_cfg_allow_open_filename(&cfg, "/dev/random"); + } sandbox_cfg_allow_execve(&cfg, "/usr/local/bin/tor"); From 44a4464cf6d4dac88c46b8ffdb6ad002d03ade62 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Sat, 10 Aug 2013 18:04:48 +0300 Subject: [PATCH 30/81] fixed memory leak, added array filter support --- src/common/sandbox.c | 81 ++++++++++++++++++++++++++++++++- src/common/sandbox.h | 13 +++++- src/or/main.c | 104 +++++++++++++++++-------------------------- 3 files changed, 131 insertions(+), 67 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 2ba1432cf7..f2ead21e0f 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -616,7 +617,7 @@ prot_strdup(char* str) } int -sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) +sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, char fr) { sandbox_cfg_t *elem = NULL; @@ -630,11 +631,37 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) elem->next = *cfg; *cfg = elem; + if (fr) tor_free_(file); + return 0; } int -sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file) +sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, int num, ...) +{ + int rc = 0, i; + + va_list ap; + va_start(ap, num); + + for (i = 0; i < num; i++) { + char *fn = va_arg(ap, char*); + char fr = (char) va_arg(ap, int); + + rc = sandbox_cfg_allow_open_filename(cfg, fn, fr); + if(rc) { + log_err(LD_BUG,"(Sandbox) failed on par %d", i); + goto end; + } + } + + end: + va_end(ap); + return 0; +} + +int +sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, char fr) { sandbox_cfg_t *elem = NULL; @@ -648,6 +675,32 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file) elem->next = *cfg; *cfg = elem; + if (fr) tor_free_(file); + + return 0; +} + +int +sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, int num, ...) +{ + int rc = 0, i; + + va_list ap; + va_start(ap, num); + + for (i = 0; i < num; i++) { + char *fn = va_arg(ap, char*); + char fr = (char) va_arg(ap, int); + + rc = sandbox_cfg_allow_openat_filename(cfg, fn, fr); + if(rc) { + log_err(LD_BUG,"(Sandbox) failed on par %d", i); + goto end; + } + } + + end: + va_end(ap); return 0; } @@ -669,6 +722,30 @@ sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com) return 0; } +int +sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, int num, ...) +{ + int rc = 0, i; + + va_list ap; + va_start(ap, num); + + for (i = 0; i < num; i++) { + char *fn = va_arg(ap, char*); + + rc = sandbox_cfg_allow_execve(cfg, fn); + + if(rc) { + log_err(LD_BUG,"(Sandbox) failed on par %d", i); + goto end; + } + } + + end: + va_end(ap); + return 0; +} + static int add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) { diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 2b265443f8..33668d964f 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -98,9 +98,18 @@ int tor_global_sandbox(void); const char* sandbox_intern_string(const char *param); sandbox_cfg_t * sandbox_cfg_new(); -int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file); -int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file); + +int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, + char fr); +int sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, int num, ...); + +int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, + char fr); +int sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, int num, ...); + int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com); +int sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, int num, ...); + int sandbox_init(sandbox_cfg_t* cfg); #endif /* SANDBOX_H_ */ diff --git a/src/or/main.c b/src/or/main.c index 36acde431a..c236e8399d 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2644,73 +2644,51 @@ sandbox_init_filter() { sandbox_cfg_t *cfg = sandbox_cfg_new(); - // TODO: mem leak - sandbox_cfg_allow_openat_filename(&cfg, get_datadir_fname("cached-status")); + sandbox_cfg_allow_openat_filename(&cfg, + get_datadir_fname("cached-status"), 1); - sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-certs")); - sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-certs.tmp")); - sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-consensus")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("unverified-consensus")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-microdesc-consensus")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-microdesc-consensus.tmp")); - sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-microdescs")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-microdescs.tmp")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-microdescs.new")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-microdescs.new.tmp")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("unverified-microdesc-consensus")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-descriptors")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-descriptors.new")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-descriptors.tmp")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-descriptors.new.tmp")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-descriptors.tmp.tmp")); - sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("cached-extrainfo")); - sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("state.tmp")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("unparseable-desc.tmp")); - sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("unparseable-desc")); + sandbox_cfg_allow_open_filename_array(&cfg, 22, + get_datadir_fname("cached-certs"), 1, + get_datadir_fname("cached-certs.tmp"), 1, + get_datadir_fname("cached-consensus"), 1, + get_datadir_fname("unverified-consensus"), 1, + get_datadir_fname("cached-microdesc-consensus"), 1, + get_datadir_fname("cached-microdesc-consensus.tmp"), 1, + get_datadir_fname("cached-microdescs"), 1, + get_datadir_fname("cached-microdescs.tmp"), 1, + get_datadir_fname("cached-microdescs.new"), 1, + get_datadir_fname("cached-microdescs.new.tmp"), 1, + get_datadir_fname("unverified-microdesc-consensus"), 1, + get_datadir_fname("cached-descriptors"), 1, + get_datadir_fname("cached-descriptors.new"), 1, + get_datadir_fname("cached-descriptors.tmp"), 1, + get_datadir_fname("cached-descriptors.new.tmp"), 1, + get_datadir_fname("cached-descriptors.tmp.tmp"), 1, + get_datadir_fname("cached-extrainfo"), 1, + get_datadir_fname("state.tmp"), 1, + get_datadir_fname("unparseable-desc.tmp"), 1, + get_datadir_fname("unparseable-desc"), 1, + "/dev/srandom", 0, + "/dev/urandom", 0 + ); // orport if (server_mode(get_options())) { - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname2("keys", "secret_id_key")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname2("keys", "secret_onion_key")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname2("keys", "secret_onion_key_ntor")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname2("keys", "secret_onion_key_ntor.tmp")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname2("keys", "secret_id_key.old")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname2("keys", "secret_onion_key.old")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname2("keys", "secret_onion_key_ntor.old")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname2("keys", "secret_onion_key.tmp")); - - sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname("fingerprint")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-consensus.tmp")); - sandbox_cfg_allow_open_filename(&cfg, - get_datadir_fname("cached-consensus")); - - sandbox_cfg_allow_open_filename(&cfg, "/etc/resolv.conf"); - sandbox_cfg_allow_open_filename(&cfg, "/dev/srandom"); - sandbox_cfg_allow_open_filename(&cfg, "/dev/urandom"); - sandbox_cfg_allow_open_filename(&cfg, "/dev/random"); - + sandbox_cfg_allow_open_filename_array(&cfg, 13, + get_datadir_fname2("keys", "secret_id_key"), 1, + get_datadir_fname2("keys", "secret_onion_key"), 1, + get_datadir_fname2("keys", "secret_onion_key_ntor"), 1, + get_datadir_fname2("keys", "secret_onion_key_ntor.tmp"), 1, + get_datadir_fname2("keys", "secret_id_key.old"), 1, + get_datadir_fname2("keys", "secret_onion_key.old"), 1, + get_datadir_fname2("keys", "secret_onion_key_ntor.old"), 1, + get_datadir_fname2("keys", "secret_onion_key.tmp"), 1, + get_datadir_fname("fingerprint"), 1, + get_datadir_fname("cached-consensus"), 1, + get_datadir_fname("cached-consensus.tmp"), 1, + "/etc/resolv.conf", 0, + "/dev/random", 0 + ); } sandbox_cfg_allow_execve(&cfg, "/usr/local/bin/tor"); From 8a85a48b9d0ed2b298bcc26dfeb96fa7e31c05c4 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 12 Aug 2013 21:14:43 +0300 Subject: [PATCH 31/81] attempt to add stat64 filename filters; failed due to getaddrinfo.. --- src/common/sandbox.c | 80 +++++++++++++++++++++++++++++++++++++++++--- src/common/sandbox.h | 7 ++++ src/common/util.c | 4 +-- src/or/config.c | 2 +- src/or/dns.c | 3 +- src/or/main.c | 13 +++++++ 6 files changed, 100 insertions(+), 9 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index f2ead21e0f..0be4c5235c 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -97,16 +97,14 @@ static int filter_nopar_gen[] = { SCMP_SYS(sigreturn), #endif SCMP_SYS(stat), -#ifdef __NR_stat64 - SCMP_SYS(stat64), // TODO -#endif SCMP_SYS(uname), SCMP_SYS(write), SCMP_SYS(exit_group), SCMP_SYS(exit), SCMP_SYS(madvise), - + // getaddrinfo uses this.. + SCMP_SYS(stat64), // Not needed.. // SCMP_SYS(set_thread_area), // SCMP_SYS(set_tid_address), @@ -542,6 +540,31 @@ sb_poll(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +#ifdef __NR_stat64 +static int +sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +{ + int rc = 0; + sandbox_cfg_t *elem = NULL; + + // for each dynamic parameter filters + for (elem = filter; elem != NULL; elem = elem->next) { + if (elem->prot == 1 && (elem->syscall == SCMP_SYS(open) || + elem->syscall == SCMP_SYS(stat64))) { + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64), 1, + SCMP_CMP(0, SCMP_CMP_EQ, elem->param)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " + "error %d", rc); + return rc; + } + } + } + + return 0; +} +#endif + static sandbox_filter_func_t filter_func[] = { sb_rt_sigaction, sb_rt_sigprocmask, @@ -559,7 +582,8 @@ static sandbox_filter_func_t filter_func[] = { sb_flock, sb_futex, sb_mremap, - sb_poll + sb_poll, + sb_stat64 }; const char* @@ -616,6 +640,52 @@ prot_strdup(char* str) return res; } +#ifdef __NR_stat64 +int +sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, char fr) +{ + sandbox_cfg_t *elem = NULL; + + elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); + elem->syscall = SCMP_SYS(stat64); + elem->pindex = 0; + elem->ptype = PARAM_PTR; + elem->param = (intptr_t) prot_strdup((char*) file); + elem->prot = 1; + + elem->next = *cfg; + *cfg = elem; + + if (fr) tor_free_(file); + + return 0; +} + +int +sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, int num, ...) +{ + int rc = 0, i; + + va_list ap; + va_start(ap, num); + + for (i = 0; i < num; i++) { + char *fn = va_arg(ap, char*); + char fr = (char) va_arg(ap, int); + + rc = sandbox_cfg_allow_stat64_filename(cfg, fn, fr); + if(rc) { + log_err(LD_BUG,"(Sandbox) failed on par %d", i); + goto end; + } + } + + end: + va_end(ap); + return 0; +} +#endif + int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, char fr) { diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 33668d964f..e928591602 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -9,6 +9,8 @@ * \brief Header file for sandbox.c. **/ +// TODO: thinking of only having allow_file for multiple syscalls + #ifndef SANDBOX_H_ #define SANDBOX_H_ @@ -110,6 +112,11 @@ int sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, int num, ...); int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com); int sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, int num, ...); +int sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, + char fr); +int sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, + int num, ...); + int sandbox_init(sandbox_cfg_t* cfg); #endif /* SANDBOX_H_ */ diff --git a/src/common/util.c b/src/common/util.c index 75462b68a1..8408a36f30 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -1803,7 +1803,7 @@ file_status(const char *fname) int r; f = tor_strdup(fname); clean_name_for_stat(f); - r = stat(f, &st); + r = stat(sandbox_intern_string(f), &st); tor_free(f); if (r) { if (errno == ENOENT) { @@ -1853,7 +1853,7 @@ check_private_dir(const char *dirname, cpd_check_t check, tor_assert(dirname); f = tor_strdup(dirname); clean_name_for_stat(f); - r = stat(f, &st); + r = stat(sandbox_intern_string(f), &st); tor_free(f); if (r) { if (errno != ENOENT) { diff --git a/src/or/config.c b/src/or/config.c index e53c2888f1..e1b7b4e47f 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -6121,7 +6121,7 @@ remove_file_if_very_old(const char *fname, time_t now) #define VERY_OLD_FILE_AGE (28*24*60*60) struct stat st; - if (stat(fname, &st)==0 && st.st_mtime < now-VERY_OLD_FILE_AGE) { + if (stat(sandbox_intern_string(fname), &st)==0 && st.st_mtime < now-VERY_OLD_FILE_AGE) { char buf[ISO_TIME_LEN+1]; format_local_iso_time(buf, st.st_mtime); log_notice(LD_GENERAL, "Obsolete file %s hasn't been modified since %s. " diff --git a/src/or/dns.c b/src/or/dns.c index edcf92e5b3..6dc0c05f9c 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -24,6 +24,7 @@ #include "relay.h" #include "router.h" #include "ht.h" +#include "../common/sandbox.h" #ifdef HAVE_EVENT2_DNS_H #include #include @@ -1477,7 +1478,7 @@ configure_nameservers(int force) evdns_set_log_fn(evdns_log_cb); if (conf_fname) { - if (stat(conf_fname, &st)) { + if (stat(sandbox_intern_string(conf_fname), &st)) { log_warn(LD_EXIT, "Unable to stat resolver configuration in '%s': %s", conf_fname, strerror(errno)); goto err; diff --git a/src/or/main.c b/src/or/main.c index c236e8399d..a2fbe5f636 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2672,6 +2672,14 @@ sandbox_init_filter() "/dev/urandom", 0 ); + sandbox_cfg_allow_stat64_filename_array(&cfg, 5, + get_datadir_fname(NULL), 1, + get_datadir_fname("lock"), 1, + get_datadir_fname("state"), 1, + get_datadir_fname("router-stability"), 1, + get_datadir_fname("cached-extrainfo.new"), 1 + ); + // orport if (server_mode(get_options())) { sandbox_cfg_allow_open_filename_array(&cfg, 13, @@ -2689,6 +2697,11 @@ sandbox_init_filter() "/etc/resolv.conf", 0, "/dev/random", 0 ); + + sandbox_cfg_allow_stat64_filename_array(&cfg, 2, + get_datadir_fname("keys"), 1, + get_datadir_fname("stats/dirreq-stats"), 1 + ); } sandbox_cfg_allow_execve(&cfg, "/usr/local/bin/tor"); From e2a7b484f47b242eb8399751cb0fbe73e14ef0b8 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 14 Aug 2013 23:03:38 +0300 Subject: [PATCH 32/81] partial libevent open fix --- src/common/sandbox.c | 18 ++++++------------ src/or/main.c | 14 +++++++++----- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 0be4c5235c..6ff4296c4d 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -9,6 +9,8 @@ * \brief Code to enable sandboxing. **/ +#define _LARGEFILE64_SOURCE + #include #include #include @@ -32,10 +34,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -53,6 +57,7 @@ static sandbox_cfg_t *filter_dynamic = NULL; static int filter_nopar_gen[] = { SCMP_SYS(access), SCMP_SYS(brk), + SCMP_SYS(clock_gettime), SCMP_SYS(close), SCMP_SYS(clone), SCMP_SYS(epoll_create), @@ -105,9 +110,6 @@ static int filter_nopar_gen[] = { SCMP_SYS(madvise), // getaddrinfo uses this.. SCMP_SYS(stat64), - // Not needed.. -// SCMP_SYS(set_thread_area), -// SCMP_SYS(set_tid_address), // socket syscalls SCMP_SYS(bind), @@ -263,7 +265,7 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) // todo remove when libevent fix rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, - SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY)); + SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY|O_LARGEFILE|O_CLOEXEC)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " "error %d", rc); @@ -305,13 +307,6 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } -static int -sb_clock_gettime(scmp_filter_ctx ctx, sandbox_cfg_t *filter) -{ - return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(clock_gettime), 1, - SCMP_CMP(0, SCMP_CMP_EQ, CLOCK_MONOTONIC)); -} - // TODO: param not working static int sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) @@ -574,7 +569,6 @@ static sandbox_filter_func_t filter_func[] = { sb_mmap2, sb_open, sb_openat, - sb_clock_gettime, sb_fcntl64, sb_epoll_ctl, sb_prctl, diff --git a/src/or/main.c b/src/or/main.c index a2fbe5f636..9d0719c464 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2647,7 +2647,7 @@ sandbox_init_filter() sandbox_cfg_allow_openat_filename(&cfg, get_datadir_fname("cached-status"), 1); - sandbox_cfg_allow_open_filename_array(&cfg, 22, + sandbox_cfg_allow_open_filename_array(&cfg, 23, get_datadir_fname("cached-certs"), 1, get_datadir_fname("cached-certs.tmp"), 1, get_datadir_fname("cached-consensus"), 1, @@ -2669,7 +2669,8 @@ sandbox_init_filter() get_datadir_fname("unparseable-desc.tmp"), 1, get_datadir_fname("unparseable-desc"), 1, "/dev/srandom", 0, - "/dev/urandom", 0 + "/dev/urandom", 0, + "/dev/random", 0 ); sandbox_cfg_allow_stat64_filename_array(&cfg, 5, @@ -2682,7 +2683,7 @@ sandbox_init_filter() // orport if (server_mode(get_options())) { - sandbox_cfg_allow_open_filename_array(&cfg, 13, + sandbox_cfg_allow_open_filename_array(&cfg, 12, get_datadir_fname2("keys", "secret_id_key"), 1, get_datadir_fname2("keys", "secret_onion_key"), 1, get_datadir_fname2("keys", "secret_onion_key_ntor"), 1, @@ -2694,8 +2695,7 @@ sandbox_init_filter() get_datadir_fname("fingerprint"), 1, get_datadir_fname("cached-consensus"), 1, get_datadir_fname("cached-consensus.tmp"), 1, - "/etc/resolv.conf", 0, - "/dev/random", 0 + "/etc/resolv.conf", 0 ); sandbox_cfg_allow_stat64_filename_array(&cfg, 2, @@ -2783,6 +2783,10 @@ tor_main(int argc, char *argv[]) log_err(LD_BUG,"Failed to create syscall sandbox filter"); return -1; } + + // registering libevent rng + evutil_secure_rng_set_urandom_device_file( + (char*) sandbox_intern_string("/dev/random")); } switch (get_options()->command) { From 372e0f91fdb8baa43a6495c66d8df9d9d64f711c Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 15 Aug 2013 00:09:07 +0300 Subject: [PATCH 33/81] added comments for sandbox.h --- src/common/compat.c | 1 + src/common/sandbox.c | 13 ++---- src/common/sandbox.h | 106 +++++++++++++++++++++++++++++++++++-------- 3 files changed, 92 insertions(+), 28 deletions(-) diff --git a/src/common/compat.c b/src/common/compat.c index 47b65d3560..adabf6edd5 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -109,6 +109,7 @@ #include "util.h" #include "container.h" #include "address.h" +#include "sandbox.h" /* Inline the strl functions if the platform doesn't have them. */ #ifndef HAVE_STRLCPY diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 6ff4296c4d..f4c0779796 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -9,6 +9,10 @@ * \brief Code to enable sandboxing. **/ +/** + * Temporarily required for O_LARGEFILE flag. Needs to be removed + * with the libevent fix. + */ #define _LARGEFILE64_SOURCE #include @@ -243,7 +247,6 @@ sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } #endif -// TODO parameters static int sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -589,8 +592,7 @@ sandbox_intern_string(const char *param) return NULL; for (elem = filter_dynamic; elem != NULL; elem = elem->next) { - if (elem->prot && elem->ptype == PARAM_PTR - && !strncmp(param, (char*)(elem->param), MAX_PARAM_LEN)) { + if (elem->prot && !strncmp(param, (char*)(elem->param), MAX_PARAM_LEN)) { return (char*)(elem->param); } } @@ -643,7 +645,6 @@ sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, char fr) elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); elem->syscall = SCMP_SYS(stat64); elem->pindex = 0; - elem->ptype = PARAM_PTR; elem->param = (intptr_t) prot_strdup((char*) file); elem->prot = 1; @@ -688,7 +689,6 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, char fr) elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); elem->syscall = SCMP_SYS(open); elem->pindex = 0; - elem->ptype = PARAM_PTR; elem->param = (intptr_t) prot_strdup((char*) file); elem->prot = 1; @@ -732,7 +732,6 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, char fr) elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); elem->syscall = SCMP_SYS(openat); elem->pindex = 1; - elem->ptype = PARAM_PTR; elem->param = (intptr_t) prot_strdup((char*) file);; elem->prot = 1; @@ -776,7 +775,6 @@ sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com) elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); elem->syscall = SCMP_SYS(openat); elem->pindex = 1; - elem->ptype = PARAM_PTR; elem->param = (intptr_t) prot_strdup((char*) com);; elem->prot = 1; @@ -1062,7 +1060,6 @@ tor_global_sandbox(void) #endif } -/** Use fd to log non-survivable sandbox violations. */ void sandbox_set_debugging_fd(int fd) { diff --git a/src/common/sandbox.h b/src/common/sandbox.h index e928591602..ad31e54100 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -9,8 +9,6 @@ * \brief Header file for sandbox.c. **/ -// TODO: thinking of only having allow_file for multiple syscalls - #ifndef SANDBOX_H_ #define SANDBOX_H_ @@ -37,40 +35,38 @@ #include #include +/** Security measure for filter string parameter lengths*/ #define MAX_PARAM_LEN 64 #define PARAM_PTR 0 #define PARAM_NUM 1 -typedef struct { - int syscall; - - char ptype; - char pindex; - intptr_t param; - - char prot; -} sandbox_static_cfg_t; - +/** + * Structure used to manage a sandbox configuration. + * + * It is implemented as a linked list of parameters. Currently only controls + * parameters for open, openat, execve, stat64. + */ struct pfd_elem { - int syscall; + int syscall; // syscall associated with parameter - char ptype; - char pindex; - intptr_t param; + char pindex; // parameter index + intptr_t param; // parameter value - char prot; + char prot; // parameter flag (0 = not protected, 1 = protected) struct pfd_elem *next; }; +/** Typedef to structure used to manage a sandbox configuration. */ typedef struct pfd_elem sandbox_cfg_t; +/** Function pointer defining the prototype of a filter function.*/ typedef int (*sandbox_filter_func_t)(scmp_filter_ctx ctx, sandbox_cfg_t *filter); - +/** Type that will be used in step 3 in order to manage multiple sandboxes.*/ typedef struct { - // function pointers associated with filter + // function pointers associated with the filter sandbox_filter_func_t *filter_func; // filter function pointer parameters @@ -95,28 +91,98 @@ typedef struct { #endif // __linux__ +/** Use fd to log non-survivable sandbox violations. */ void sandbox_set_debugging_fd(int fd); -int tor_global_sandbox(void); + +/** Returns a registered protected string used with the sandbox, given that + * it matches the parameter. + */ const char* sandbox_intern_string(const char *param); +/** Creates an empty sandbox configuration file.*/ sandbox_cfg_t * sandbox_cfg_new(); +/** + * Function used to add a open allowed filename to a supplied configuration. + * The (char*) specifies the path to the allowed file, fr = 1 tells the + * function that the char* needs to be free-ed, 0 means the pointer does not + * need to be free-ed. + */ int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, char fr); + +/** Function used to add a series of open allowed filenames to a supplied + * configuration. + * @param cfg sandbox configuration. + * @param num number of files. + * @param ... all future parameters are specified as pairs of <(char*), 1 / 0> + * the char* specifies the path to the allowed file, 1 tells the function + * that the char* needs to be free-ed, 0 means the pointer does not need to + * be free-ed. + */ int sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, int num, ...); +/** + * Function used to add a openat allowed filename to a supplied configuration. + * The (char*) specifies the path to the allowed file, fr = 1 tells the + * function that the char* needs to be free-ed, 0 means the pointer does not + * need to be free-ed. + */ int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, char fr); + +/** Function used to add a series of openat allowed filenames to a supplied + * configuration. + * @param cfg sandbox configuration. + * @param num number of files. + * @param ... all future parameters are specified as pairs of <(char*), 1 / 0> + * the char* specifies the path to the allowed file, 1 tells the function + * that the char* needs to be free-ed, 0 means the pointer does not need to + * be free-ed. + */ int sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, int num, ...); +/** + * Function used to add a execve allowed filename to a supplied configuration. + * The (char*) specifies the path to the allowed file, fr = 1 tells the + * function that the char* needs to be free-ed, 0 means the pointer does not + * need to be free-ed. + */ int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com); + +/** Function used to add a series of execve allowed filenames to a supplied + * configuration. + * @param cfg sandbox configuration. + * @param num number of files. + * @param ... all future parameters are specified as pairs of <(char*), 1 / 0> + * the char* specifies the path to the allowed file, 1 tells the function + * that the char* needs to be free-ed, 0 means the pointer does not need to + * be free-ed. + */ int sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, int num, ...); +/** + * Function used to add a stat64 allowed filename to a supplied configuration. + * The (char*) specifies the path to the allowed file, fr = 1 tells the + * function that the char* needs to be free-ed, 0 means the pointer does not + * need to be free-ed. + */ int sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, char fr); + +/** Function used to add a series of stat64 allowed filenames to a supplied + * configuration. + * @param cfg sandbox configuration. + * @param num number of files. + * @param ... all future parameters are specified as pairs of <(char*), 1 / 0> + * the char* specifies the path to the allowed file, 1 tells the function + * that the char* needs to be free-ed, 0 means the pointer does not need to + * be free-ed. + */ int sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, int num, ...); +/** Function used to initialise a sandbox configuration.*/ int sandbox_init(sandbox_cfg_t* cfg); #endif /* SANDBOX_H_ */ From 863dd4d4b30f03313189ba40509ae114adbd7f60 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 15 Aug 2013 00:23:51 +0300 Subject: [PATCH 34/81] received feedback and fixed (partly) the socket filters --- src/common/sandbox.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index f4c0779796..6f95f64931 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -125,8 +125,6 @@ static int filter_nopar_gen[] = { SCMP_SYS(recvmsg), SCMP_SYS(sendto), SCMP_SYS(send), - SCMP_SYS(setsockopt), - SCMP_SYS(socket), SCMP_SYS(socketpair), SCMP_SYS(recvfrom), SCMP_SYS(unlink), @@ -310,32 +308,30 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } -// TODO: param not working +// TODO: add correct param static int sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; - rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 4, - SCMP_CMP(0, SCMP_CMP_EQ, 1), - SCMP_CMP(1, SCMP_CMP_EQ, PF_INET), - SCMP_CMP(2, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC), - SCMP_CMP(3, SCMP_CMP_EQ, IPPROTO_TCP)); + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3, + SCMP_CMP(0, SCMP_CMP_EQ, PF_INET), + SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC), + SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_TCP)); if (rc) return rc; - rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 4, - SCMP_CMP(0, SCMP_CMP_EQ, 1), - SCMP_CMP(1, SCMP_CMP_EQ, PF_NETLINK), - SCMP_CMP(2, SCMP_CMP_EQ, SOCK_RAW), - SCMP_CMP(3, SCMP_CMP_EQ, 0)); + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3, + SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK), + SCMP_CMP(1, SCMP_CMP_EQ, SOCK_RAW), + SCMP_CMP(2, SCMP_CMP_EQ, 0)); if (rc) return rc; return 0; } -// TODO: param not working +// TODO: add correct param static int sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -580,7 +576,10 @@ static sandbox_filter_func_t filter_func[] = { sb_futex, sb_mremap, sb_poll, - sb_stat64 + sb_stat64, + + sb_socket, + sb_setsockopt }; const char* From c09b11b6d8595ef9d39f39d2060497e67cf3e756 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Fri, 16 Aug 2013 01:43:09 +0300 Subject: [PATCH 35/81] updated filters --- src/common/sandbox.c | 84 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 6f95f64931..c5e12311c2 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -119,15 +119,12 @@ static int filter_nopar_gen[] = { SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname), - SCMP_SYS(getsockopt), - SCMP_SYS(listen), SCMP_SYS(recv), SCMP_SYS(recvmsg), + SCMP_SYS(recvfrom), SCMP_SYS(sendto), SCMP_SYS(send), - SCMP_SYS(socketpair), - SCMP_SYS(recvfrom), - SCMP_SYS(unlink), + SCMP_SYS(unlink) // ? }; static int @@ -285,7 +282,6 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } -// TODO parameters static int sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -296,7 +292,10 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) for (elem = filter; elem != NULL; elem = elem->next) { if (elem->prot == 1 && elem->syscall == SCMP_SYS(openat)) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 1, - SCMP_CMP(1, SCMP_CMP_EQ, elem->param)); + SCMP_CMP(0, SCMP_CMP_EQ, AT_FDCWD), + SCMP_CMP(1, SCMP_CMP_EQ, elem->param), + SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY| + O_CLOEXEC)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received libseccomp " "error %d", rc); @@ -308,12 +307,24 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } -// TODO: add correct param static int sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; +#ifdef __i386__ + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0); + if (rc) + return rc; +#endif + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3, + SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE), + SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK), + SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP)); + if (rc) + return rc; + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3, SCMP_CMP(0, SCMP_CMP_EQ, PF_INET), SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC), @@ -321,6 +332,13 @@ sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (rc) return rc; + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3, + SCMP_CMP(0, SCMP_CMP_EQ, PF_INET), + SCMP_CMP(1, SCMP_CMP_EQ, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK), + SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP)); + if (rc) + return rc; + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 3, SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK), SCMP_CMP(1, SCMP_CMP_EQ, SOCK_RAW), @@ -331,12 +349,37 @@ sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } -// TODO: add correct param +static int +sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +{ + int rc = 0; + +#ifdef __i386__ + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 0); + if (rc) + return rc; +#endif + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 2, + SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE), + SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC)); + if (rc) + return rc; + + return 0; +} + static int sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; +#ifdef __i386__ + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 0); + if (rc) + return rc; +#endif + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 2, SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET), SCMP_CMP(2, SCMP_CMP_EQ, SO_REUSEADDR)); @@ -346,6 +389,25 @@ sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +static int sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +{ + int rc = 0; + +#ifdef __i386__ + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), 0); + if (rc) + return rc; +#endif + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), 2, + SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET), + SCMP_CMP(2, SCMP_CMP_EQ, SO_ERROR)); + if (rc) + return rc; + + return 0; +} + #ifdef __NR_fcntl64 static int sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) @@ -579,7 +641,9 @@ static sandbox_filter_func_t filter_func[] = { sb_stat64, sb_socket, - sb_setsockopt + sb_setsockopt, + sb_getsockopt, + sb_socketpair }; const char* From a9910d89f170933a7730798c98ebbb1d743a1c46 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 19 Aug 2013 11:41:46 +0300 Subject: [PATCH 36/81] finalised fix on libevent open string issue --- src/common/sandbox.c | 9 --------- src/or/dns.c | 12 +++++++++--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index c5e12311c2..210aa7c860 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -261,15 +261,6 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } } - // todo remove when libevent fix - rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, - SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY|O_LARGEFILE|O_CLOEXEC)); - if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " - "error %d", rc); - return rc; - } - // problem: required by getaddrinfo rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY|O_CLOEXEC)); diff --git a/src/or/dns.c b/src/or/dns.c index 6dc0c05f9c..09601e9cb1 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -1444,13 +1444,14 @@ configure_nameservers(int force) const or_options_t *options; const char *conf_fname; struct stat st; - int r; + int r, flags; options = get_options(); conf_fname = options->ServerDNSResolvConfFile; #ifndef _WIN32 if (!conf_fname) conf_fname = "/etc/resolv.conf"; #endif + flags = DNS_OPTIONS_ALL; if (!the_evdns_base) { if (!(the_evdns_base = evdns_base_new(tor_libevent_get_base(), 0))) { @@ -1492,9 +1493,14 @@ configure_nameservers(int force) evdns_base_search_clear(the_evdns_base); evdns_base_clear_nameservers_and_suspend(the_evdns_base); } + if (flags & DNS_OPTION_HOSTSFILE) { + flags ^= DNS_OPTION_HOSTSFILE; + evdns_base_load_hosts(the_evdns_base, + sandbox_intern_string("/etc/resolv.conf")); + } log_info(LD_EXIT, "Parsing resolver configuration in '%s'", conf_fname); - if ((r = evdns_base_resolv_conf_parse(the_evdns_base, - DNS_OPTIONS_ALL, conf_fname))) { + if ((r = evdns_base_resolv_conf_parse(the_evdns_base, flags, + sandbox_intern_string(conf_fname)))) { log_warn(LD_EXIT, "Unable to parse '%s', or no nameservers in '%s' (%d)", conf_fname, conf_fname, r); goto err; From 36aeca0ecf5f6e724a4d5da1795c9c9d76410290 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 19 Aug 2013 13:56:50 +0300 Subject: [PATCH 37/81] fix for getaddrinfo open syscall --- src/common/address.c | 3 +- src/common/sandbox.c | 72 ++++++++++++++++++++++++++++++++++++++------ src/common/sandbox.h | 4 +++ 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/common/address.c b/src/common/address.c index 227b4fbaee..5c8603ee20 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -14,6 +14,7 @@ #include "address.h" #include "torlog.h" #include "container.h" +#include "sandbox.h" #ifdef _WIN32 #include @@ -234,7 +235,7 @@ tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr) memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; - err = getaddrinfo(name, NULL, &hints, &res); + err = sandbox_getaddrinfo(name, &res); if (!err) { best = NULL; for (res_p = res; res_p; res_p = res_p->ai_next) { diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 210aa7c860..c71efb02da 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -55,6 +55,8 @@ static sandbox_cfg_t *filter_dynamic = NULL; +static struct addrinfo *sb_addr_info= NULL; + /** Variable used for storing all syscall numbers that will be allowed with the * stage 1 general Tor sandbox. */ @@ -262,13 +264,13 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } // problem: required by getaddrinfo - rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, - SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY|O_CLOEXEC)); - if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " - "error %d", rc); - return rc; - } +// rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, +// SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY|O_CLOEXEC)); +// if (rc != 0) { +// log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " +// "error %d", rc); +// return rc; +// } return 0; } @@ -288,8 +290,8 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY| O_CLOEXEC)); if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received libseccomp " - "error %d", rc); + log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received " + "libseccomp error %d", rc); return rc; } } @@ -862,6 +864,54 @@ sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, int num, ...) return 0; } +int sandbox_getaddrinfo(const char *name, struct addrinfo **res) +{ + char hname[256]; + + if (!res) { + return -2; + } + *res = NULL; + + if (gethostname(hname, sizeof(hname)) < 0) { + return -1; + } + + if (strncmp(name, hname, sizeof(hname)) || sb_addr_info == NULL) { + log_err(LD_BUG,"(Sandbox) failed for hname %s!", name); + return -1; + } + + *res = sb_addr_info; + return 0; +} + +static int +init_addrinfo(void) +{ + int ret; + struct addrinfo hints; + char hname[256]; + + sb_addr_info = NULL; + + if (gethostname(hname, sizeof(hname)) < 0) { + return -1; + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + ret = getaddrinfo(hname, NULL, &hints, &sb_addr_info); + if(ret) { + sb_addr_info = NULL; + return -2; + } + + return 0; +} + static int add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) { @@ -1047,6 +1097,10 @@ initialise_libseccomp_sandbox(sandbox_cfg_t* cfg) if (install_sigsys_debugging()) return -1; + if (init_addrinfo()) { + return -4; + } + if (install_syscall_filter(cfg)) return -2; diff --git a/src/common/sandbox.h b/src/common/sandbox.h index ad31e54100..6cb827e268 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -34,6 +34,7 @@ #endif #include #include +#include /** Security measure for filter string parameter lengths*/ #define MAX_PARAM_LEN 64 @@ -91,6 +92,9 @@ typedef struct { #endif // __linux__ +/** Replacement for getaddrinfo(), using pre-recorded results. */ +int sandbox_getaddrinfo(const char *name, struct addrinfo **res); + /** Use fd to log non-survivable sandbox violations. */ void sandbox_set_debugging_fd(int fd); From 71612f00ae6df941861fbd9c67f0bbf15256b873 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 20 Aug 2013 13:10:07 +0300 Subject: [PATCH 38/81] fixed openssl open syscall, fixed sandbox_getaddrinfo --- src/common/sandbox.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index c71efb02da..87c8946bc1 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -264,13 +264,13 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } // problem: required by getaddrinfo -// rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, -// SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY|O_CLOEXEC)); -// if (rc != 0) { -// log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " -// "error %d", rc); -// return rc; -// } + rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(1), SCMP_SYS(open), 1, + SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY|O_CLOEXEC)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " + "error %d", rc); + return rc; + } return 0; } @@ -872,6 +872,10 @@ int sandbox_getaddrinfo(const char *name, struct addrinfo **res) return -2; } *res = NULL; + *res = (struct addrinfo *) malloc (sizeof(struct addrinfo)); + if (!res) { + return -2; + } if (gethostname(hname, sizeof(hname)) < 0) { return -1; @@ -882,7 +886,7 @@ int sandbox_getaddrinfo(const char *name, struct addrinfo **res) return -1; } - *res = sb_addr_info; + memcpy(*res, sb_addr_info, sizeof(struct addrinfo)); return 0; } From 8aa5517ff639fe7101de34c24701057d56a44346 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 21 Aug 2013 13:38:00 +0300 Subject: [PATCH 39/81] fix: flock filter update --- src/common/sandbox.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 87c8946bc1..7ff0fb0afa 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -531,6 +531,11 @@ sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (rc) return rc; + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock), 1, + SCMP_CMP(1, SCMP_CMP_EQ, LOCK_UN)); + if (rc) + return rc; + return 0; } From ed4968315ec5d0f9c41317bef5468f9019e435b9 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 21 Aug 2013 13:43:44 +0300 Subject: [PATCH 40/81] fix: sandbox_intern_string log clean up --- src/common/sandbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 7ff0fb0afa..3fb75ef80c 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -658,7 +658,7 @@ sandbox_intern_string(const char *param) } } - log_warn(LD_BUG, "(Sandbox) Parameter %s not found", param); + log_info(LD_GENERAL, "(Sandbox) Parameter %s not found", param); return param; } From bc19ea100cf85c458cce7d91b84c0b6f8892f71d Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 21 Aug 2013 17:57:15 +0300 Subject: [PATCH 41/81] make check-spaces fixes --- src/common/sandbox.c | 34 +++++++++++++++++++--------------- src/or/config.c | 3 ++- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 3fb75ef80c..a4a93dbfa5 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -161,8 +161,8 @@ sb_execve(scmp_filter_ctx ctx, sandbox_cfg_t *filter) rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), 1, SCMP_CMP(0, SCMP_CMP_EQ, elem->param)); if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add execve syscall, received libseccomp " - "error %d", rc); + log_err(LD_BUG,"(Sandbox) failed to add execve syscall, received " + "libseccomp error %d", rc); return rc; } } @@ -256,8 +256,8 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, SCMP_CMP(0, SCMP_CMP_EQ, elem->param)); if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " - "error %d", rc); + log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " + "libseccomp error %d", rc); return rc; } } @@ -382,7 +382,8 @@ sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } -static int sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +static int +sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; @@ -608,8 +609,8 @@ sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64), 1, SCMP_CMP(0, SCMP_CMP_EQ, elem->param)); if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " - "error %d", rc); + log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " + "libseccomp error %d", rc); return rc; } } @@ -730,7 +731,7 @@ sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, int num, ...) char fr = (char) va_arg(ap, int); rc = sandbox_cfg_allow_stat64_filename(cfg, fn, fr); - if(rc) { + if (rc) { log_err(LD_BUG,"(Sandbox) failed on par %d", i); goto end; } @@ -774,7 +775,7 @@ sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, int num, ...) char fr = (char) va_arg(ap, int); rc = sandbox_cfg_allow_open_filename(cfg, fn, fr); - if(rc) { + if (rc) { log_err(LD_BUG,"(Sandbox) failed on par %d", i); goto end; } @@ -817,7 +818,7 @@ sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, int num, ...) char fr = (char) va_arg(ap, int); rc = sandbox_cfg_allow_openat_filename(cfg, fn, fr); - if(rc) { + if (rc) { log_err(LD_BUG,"(Sandbox) failed on par %d", i); goto end; } @@ -858,7 +859,7 @@ sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, int num, ...) rc = sandbox_cfg_allow_execve(cfg, fn); - if(rc) { + if (rc) { log_err(LD_BUG,"(Sandbox) failed on par %d", i); goto end; } @@ -869,7 +870,8 @@ sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, int num, ...) return 0; } -int sandbox_getaddrinfo(const char *name, struct addrinfo **res) +int +sandbox_getaddrinfo(const char *name, struct addrinfo **res) { char hname[256]; @@ -877,7 +879,7 @@ int sandbox_getaddrinfo(const char *name, struct addrinfo **res) return -2; } *res = NULL; - *res = (struct addrinfo *) malloc (sizeof(struct addrinfo)); + *res = (struct addrinfo *)malloc(sizeof(struct addrinfo)); if (!res) { return -2; } @@ -913,7 +915,7 @@ init_addrinfo(void) hints.ai_socktype = SOCK_STREAM; ret = getaddrinfo(hname, NULL, &hints, &sb_addr_info); - if(ret) { + if (ret) { sb_addr_info = NULL; return -2; } @@ -1078,7 +1080,9 @@ install_sigsys_debugging(void) return 0; } -static int register_cfg(sandbox_cfg_t* cfg) { +static int +register_cfg(sandbox_cfg_t* cfg) +{ sandbox_cfg_t *elem = NULL; if (filter_dynamic == NULL) { diff --git a/src/or/config.c b/src/or/config.c index e1b7b4e47f..75ec0975a2 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -6121,7 +6121,8 @@ remove_file_if_very_old(const char *fname, time_t now) #define VERY_OLD_FILE_AGE (28*24*60*60) struct stat st; - if (stat(sandbox_intern_string(fname), &st)==0 && st.st_mtime < now-VERY_OLD_FILE_AGE) { + if (stat(sandbox_intern_string(fname), &st)==0 && + st.st_mtime < now-VERY_OLD_FILE_AGE) { char buf[ISO_TIME_LEN+1]; format_local_iso_time(buf, st.st_mtime); log_notice(LD_GENERAL, "Obsolete file %s hasn't been modified since %s. " From b10472f92bfe6f4f6c60b70b270df71d1fb95d76 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 21 Aug 2013 19:01:01 +0300 Subject: [PATCH 42/81] small open syscall modification (just in case) --- src/common/sandbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index a4a93dbfa5..e026c7ce3e 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -126,7 +126,7 @@ static int filter_nopar_gen[] = { SCMP_SYS(recvfrom), SCMP_SYS(sendto), SCMP_SYS(send), - SCMP_SYS(unlink) // ? + SCMP_SYS(unlink) }; static int @@ -264,7 +264,7 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } // problem: required by getaddrinfo - rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(1), SCMP_SYS(open), 1, + rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(-1), SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY|O_CLOEXEC)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " From 15d420b564d00891a9a9a388cfb187aff8a89d3b Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 26 Aug 2013 20:06:46 +0300 Subject: [PATCH 43/81] fix: accept4 for 64 bit --- src/common/sandbox.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index e026c7ce3e..79a8930156 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -181,8 +181,23 @@ sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter) static int sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { - return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 1, - SCMP_CMP(0, SCMP_CMP_EQ, 18)); + int rc = 0; + +#ifdef __i386__ + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 1, + SCMP_CMP(0, SCMP_CMP_EQ, 18)); + if (rc) { + return rc; + } +#endif + + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 1, + SCMP_CMP(3, SCMP_CMP_EQ, SOCK_CLOEXEC)); + if (rc) { + return rc; + } + + return 0; } #ifdef __NR_mmap2 From 148c6dc47348bccfd304a6ee3cd898663eef8841 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 26 Aug 2013 21:19:22 +0300 Subject: [PATCH 44/81] updated open syscall strings --- src/or/main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/or/main.c b/src/or/main.c index 9d0719c464..d0759722e2 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2647,11 +2647,12 @@ sandbox_init_filter() sandbox_cfg_allow_openat_filename(&cfg, get_datadir_fname("cached-status"), 1); - sandbox_cfg_allow_open_filename_array(&cfg, 23, + sandbox_cfg_allow_open_filename_array(&cfg, 24, get_datadir_fname("cached-certs"), 1, get_datadir_fname("cached-certs.tmp"), 1, get_datadir_fname("cached-consensus"), 1, get_datadir_fname("unverified-consensus"), 1, + get_datadir_fname("unverified-consensus.tmp"), 1, get_datadir_fname("cached-microdesc-consensus"), 1, get_datadir_fname("cached-microdesc-consensus.tmp"), 1, get_datadir_fname("cached-microdescs"), 1, @@ -2683,7 +2684,7 @@ sandbox_init_filter() // orport if (server_mode(get_options())) { - sandbox_cfg_allow_open_filename_array(&cfg, 12, + sandbox_cfg_allow_open_filename_array(&cfg, 14, get_datadir_fname2("keys", "secret_id_key"), 1, get_datadir_fname2("keys", "secret_onion_key"), 1, get_datadir_fname2("keys", "secret_onion_key_ntor"), 1, @@ -2692,7 +2693,9 @@ sandbox_init_filter() get_datadir_fname2("keys", "secret_onion_key.old"), 1, get_datadir_fname2("keys", "secret_onion_key_ntor.old"), 1, get_datadir_fname2("keys", "secret_onion_key.tmp"), 1, + get_datadir_fname2("keys", "secret_id_key.tmp"), 1, get_datadir_fname("fingerprint"), 1, + get_datadir_fname("fingerprint.tmp"), 1, get_datadir_fname("cached-consensus"), 1, get_datadir_fname("cached-consensus.tmp"), 1, "/etc/resolv.conf", 0 From b121ca581d8a2390f6aa61f6537a1884cd268c44 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 26 Aug 2013 21:28:30 +0300 Subject: [PATCH 45/81] make check-spaces fix --- src/common/sandbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 79a8930156..50d6f99b9f 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -185,14 +185,14 @@ sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter) #ifdef __i386__ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 1, - SCMP_CMP(0, SCMP_CMP_EQ, 18)); + SCMP_CMP(0, SCMP_CMP_EQ, 18)); if (rc) { return rc; } #endif rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4), 1, - SCMP_CMP(3, SCMP_CMP_EQ, SOCK_CLOEXEC)); + SCMP_CMP(3, SCMP_CMP_EQ, SOCK_CLOEXEC)); if (rc) { return rc; } From 8b8f87a06ad5f18460012d0a0b4ceaa119bbccd3 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 28 Aug 2013 19:56:42 +0300 Subject: [PATCH 46/81] removed PARAM_LEN --- src/common/sandbox.c | 9 +++------ src/common/sandbox.h | 3 --- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 50d6f99b9f..8ef8757cbf 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -669,7 +669,7 @@ sandbox_intern_string(const char *param) return NULL; for (elem = filter_dynamic; elem != NULL; elem = elem->next) { - if (elem->prot && !strncmp(param, (char*)(elem->param), MAX_PARAM_LEN)) { + if (elem->prot && !strcmp(param, (char*)(elem->param))) { return (char*)(elem->param); } } @@ -688,10 +688,7 @@ prot_strdup(char* str) goto out; // allocating protected memory region for parameter - param_size = 1 + strnlen(str, MAX_PARAM_LEN); - if (param_size == MAX_PARAM_LEN) { - log_warn(LD_BUG, "(Sandbox) Parameter length too large!"); - } + param_size = 1 + strlen(str); res = (char*) mmap(NULL, param_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); @@ -903,7 +900,7 @@ sandbox_getaddrinfo(const char *name, struct addrinfo **res) return -1; } - if (strncmp(name, hname, sizeof(hname)) || sb_addr_info == NULL) { + if (strcmp(name, hname) || sb_addr_info == NULL) { log_err(LD_BUG,"(Sandbox) failed for hname %s!", name); return -1; } diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 6cb827e268..a844fc5548 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -36,9 +36,6 @@ #include #include -/** Security measure for filter string parameter lengths*/ -#define MAX_PARAM_LEN 64 - #define PARAM_PTR 0 #define PARAM_NUM 1 From 6cae5d706c5802f28c46cece95b1cf8bd08f387a Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Wed, 28 Aug 2013 20:01:52 +0300 Subject: [PATCH 47/81] Added doxygen struct doc and replaced func() with funct(void) --- src/common/sandbox.c | 2 +- src/common/sandbox.h | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 8ef8757cbf..13d4ce927c 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -1138,7 +1138,7 @@ initialise_libseccomp_sandbox(sandbox_cfg_t* cfg) #endif // USE_LIBSECCOMP sandbox_cfg_t* -sandbox_cfg_new() +sandbox_cfg_new(void) { return NULL; } diff --git a/src/common/sandbox.h b/src/common/sandbox.h index a844fc5548..d7e1172864 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -46,12 +46,16 @@ * parameters for open, openat, execve, stat64. */ struct pfd_elem { - int syscall; // syscall associated with parameter + /** syscall associated with parameter. */ + int syscall; - char pindex; // parameter index - intptr_t param; // parameter value + /** parameter index. */ + char pindex; + /** parameter value. */ + intptr_t param; - char prot; // parameter flag (0 = not protected, 1 = protected) + /** parameter flag (0 = not protected, 1 = protected). */ + char prot; struct pfd_elem *next; }; @@ -101,7 +105,7 @@ void sandbox_set_debugging_fd(int fd); const char* sandbox_intern_string(const char *param); /** Creates an empty sandbox configuration file.*/ -sandbox_cfg_t * sandbox_cfg_new(); +sandbox_cfg_t * sandbox_cfg_new(void); /** * Function used to add a open allowed filename to a supplied configuration. From 8e2b9d28442a6291f4de5d039d4035882b12845f Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 29 Aug 2013 12:41:17 +0300 Subject: [PATCH 48/81] small fixes in documentation and sandbox_getaddrinfo() --- src/common/sandbox.c | 2 +- src/common/sandbox.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 13d4ce927c..39f6932e2a 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -892,7 +892,7 @@ sandbox_getaddrinfo(const char *name, struct addrinfo **res) } *res = NULL; *res = (struct addrinfo *)malloc(sizeof(struct addrinfo)); - if (!res) { + if (*res == NULL) { return -2; } diff --git a/src/common/sandbox.h b/src/common/sandbox.h index d7e1172864..605df7f34a 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -68,10 +68,10 @@ typedef int (*sandbox_filter_func_t)(scmp_filter_ctx ctx, /** Type that will be used in step 3 in order to manage multiple sandboxes.*/ typedef struct { - // function pointers associated with the filter + /** function pointers associated with the filter */ sandbox_filter_func_t *filter_func; - // filter function pointer parameters + /** filter function pointer parameters */ sandbox_cfg_t *filter_dynamic; } sandbox_t; From ce04d2a6220c00497a60d38b3a96385226d94866 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 29 Aug 2013 15:19:49 +0300 Subject: [PATCH 49/81] replaced boolean char with int --- src/common/sandbox.c | 12 ++++++------ src/common/sandbox.h | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 39f6932e2a..0bfbd012fd 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -712,7 +712,7 @@ prot_strdup(char* str) #ifdef __NR_stat64 int -sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, char fr) +sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; @@ -740,7 +740,7 @@ sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, int num, ...) for (i = 0; i < num; i++) { char *fn = va_arg(ap, char*); - char fr = (char) va_arg(ap, int); + int fr = va_arg(ap, int); rc = sandbox_cfg_allow_stat64_filename(cfg, fn, fr); if (rc) { @@ -756,7 +756,7 @@ sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, int num, ...) #endif int -sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, char fr) +sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; @@ -784,7 +784,7 @@ sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, int num, ...) for (i = 0; i < num; i++) { char *fn = va_arg(ap, char*); - char fr = (char) va_arg(ap, int); + int fr = va_arg(ap, int); rc = sandbox_cfg_allow_open_filename(cfg, fn, fr); if (rc) { @@ -799,7 +799,7 @@ sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, int num, ...) } int -sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, char fr) +sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; @@ -827,7 +827,7 @@ sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, int num, ...) for (i = 0; i < num; i++) { char *fn = va_arg(ap, char*); - char fr = (char) va_arg(ap, int); + int fr = va_arg(ap, int); rc = sandbox_cfg_allow_openat_filename(cfg, fn, fr); if (rc) { diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 605df7f34a..4119d9289b 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -50,12 +50,12 @@ struct pfd_elem { int syscall; /** parameter index. */ - char pindex; + int pindex; /** parameter value. */ intptr_t param; /** parameter flag (0 = not protected, 1 = protected). */ - char prot; + int prot; struct pfd_elem *next; }; @@ -114,7 +114,7 @@ sandbox_cfg_t * sandbox_cfg_new(void); * need to be free-ed. */ int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, - char fr); + int fr); /** Function used to add a series of open allowed filenames to a supplied * configuration. @@ -134,7 +134,7 @@ int sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, int num, ...); * need to be free-ed. */ int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, - char fr); + int fr); /** Function used to add a series of openat allowed filenames to a supplied * configuration. @@ -173,7 +173,7 @@ int sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, int num, ...); * need to be free-ed. */ int sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, - char fr); + int fr); /** Function used to add a series of stat64 allowed filenames to a supplied * configuration. From b1f7105506ca496a29fb4cdfd6f7f1a876a1e47b Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 29 Aug 2013 15:22:14 +0300 Subject: [PATCH 50/81] supporting /dev/urandom instead of /dev/random --- src/or/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/or/main.c b/src/or/main.c index d0759722e2..ca7e3b3e7c 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2789,7 +2789,7 @@ tor_main(int argc, char *argv[]) // registering libevent rng evutil_secure_rng_set_urandom_device_file( - (char*) sandbox_intern_string("/dev/random")); + (char*) sandbox_intern_string("/dev/urandom")); } switch (get_options()->command) { From d5f43b52546013e5fac26a1d08a9c21fb2be864a Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 29 Aug 2013 15:42:30 +0300 Subject: [PATCH 51/81] _array filter functions now rely on final NULL parameter --- src/common/sandbox.c | 49 ++++++++++++++++++++++---------------------- src/common/sandbox.h | 9 ++++---- src/or/main.c | 20 ++++++++++-------- 3 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 0bfbd012fd..49c057c2aa 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -731,20 +731,20 @@ sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, int fr) } int -sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, int num, ...) +sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, ...) { - int rc = 0, i; + int rc = 0; + char *fn = NULL; va_list ap; - va_start(ap, num); + va_start(ap, cfg); - for (i = 0; i < num; i++) { - char *fn = va_arg(ap, char*); + while((fn = va_arg(ap, char*)) != NULL) { int fr = va_arg(ap, int); rc = sandbox_cfg_allow_stat64_filename(cfg, fn, fr); if (rc) { - log_err(LD_BUG,"(Sandbox) failed on par %d", i); + log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_stat64_filename_array fail"); goto end; } } @@ -775,20 +775,20 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, int fr) } int -sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, int num, ...) +sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...) { - int rc = 0, i; + int rc = 0; + char *fn = NULL; va_list ap; - va_start(ap, num); + va_start(ap, cfg); - for (i = 0; i < num; i++) { - char *fn = va_arg(ap, char*); + while((fn = va_arg(ap, char*)) != NULL) { int fr = va_arg(ap, int); rc = sandbox_cfg_allow_open_filename(cfg, fn, fr); if (rc) { - log_err(LD_BUG,"(Sandbox) failed on par %d", i); + log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_open_filename_array fail"); goto end; } } @@ -818,20 +818,20 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, int fr) } int -sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, int num, ...) +sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...) { - int rc = 0, i; + int rc = 0; + char *fn = NULL; va_list ap; - va_start(ap, num); + va_start(ap, cfg); - for (i = 0; i < num; i++) { - char *fn = va_arg(ap, char*); + while((fn = va_arg(ap, char*)) != NULL) { int fr = va_arg(ap, int); rc = sandbox_cfg_allow_openat_filename(cfg, fn, fr); if (rc) { - log_err(LD_BUG,"(Sandbox) failed on par %d", i); + log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_openat_filename_array fail"); goto end; } } @@ -859,20 +859,19 @@ sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com) } int -sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, int num, ...) +sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) { - int rc = 0, i; + int rc = 0; + char *fn = NULL; va_list ap; - va_start(ap, num); + va_start(ap, cfg); - for (i = 0; i < num; i++) { - char *fn = va_arg(ap, char*); + while((fn = va_arg(ap, char*)) != NULL) { rc = sandbox_cfg_allow_execve(cfg, fn); - if (rc) { - log_err(LD_BUG,"(Sandbox) failed on par %d", i); + log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_execve_array failed"); goto end; } } diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 4119d9289b..2c0eb30b8b 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -125,7 +125,7 @@ int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, * that the char* needs to be free-ed, 0 means the pointer does not need to * be free-ed. */ -int sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, int num, ...); +int sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...); /** * Function used to add a openat allowed filename to a supplied configuration. @@ -145,7 +145,7 @@ int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, * that the char* needs to be free-ed, 0 means the pointer does not need to * be free-ed. */ -int sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, int num, ...); +int sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...); /** * Function used to add a execve allowed filename to a supplied configuration. @@ -164,7 +164,7 @@ int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com); * that the char* needs to be free-ed, 0 means the pointer does not need to * be free-ed. */ -int sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, int num, ...); +int sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...); /** * Function used to add a stat64 allowed filename to a supplied configuration. @@ -184,8 +184,7 @@ int sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, * that the char* needs to be free-ed, 0 means the pointer does not need to * be free-ed. */ -int sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, - int num, ...); +int sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, ...); /** Function used to initialise a sandbox configuration.*/ int sandbox_init(sandbox_cfg_t* cfg); diff --git a/src/or/main.c b/src/or/main.c index ca7e3b3e7c..861f586c90 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2647,7 +2647,7 @@ sandbox_init_filter() sandbox_cfg_allow_openat_filename(&cfg, get_datadir_fname("cached-status"), 1); - sandbox_cfg_allow_open_filename_array(&cfg, 24, + sandbox_cfg_allow_open_filename_array(&cfg, get_datadir_fname("cached-certs"), 1, get_datadir_fname("cached-certs.tmp"), 1, get_datadir_fname("cached-consensus"), 1, @@ -2671,20 +2671,22 @@ sandbox_init_filter() get_datadir_fname("unparseable-desc"), 1, "/dev/srandom", 0, "/dev/urandom", 0, - "/dev/random", 0 + "/dev/random", 0, + NULL, 0 ); - sandbox_cfg_allow_stat64_filename_array(&cfg, 5, + sandbox_cfg_allow_stat64_filename_array(&cfg, get_datadir_fname(NULL), 1, get_datadir_fname("lock"), 1, get_datadir_fname("state"), 1, get_datadir_fname("router-stability"), 1, - get_datadir_fname("cached-extrainfo.new"), 1 + get_datadir_fname("cached-extrainfo.new"), 1, + NULL, 0 ); // orport if (server_mode(get_options())) { - sandbox_cfg_allow_open_filename_array(&cfg, 14, + sandbox_cfg_allow_open_filename_array(&cfg, get_datadir_fname2("keys", "secret_id_key"), 1, get_datadir_fname2("keys", "secret_onion_key"), 1, get_datadir_fname2("keys", "secret_onion_key_ntor"), 1, @@ -2698,12 +2700,14 @@ sandbox_init_filter() get_datadir_fname("fingerprint.tmp"), 1, get_datadir_fname("cached-consensus"), 1, get_datadir_fname("cached-consensus.tmp"), 1, - "/etc/resolv.conf", 0 + "/etc/resolv.conf", 0, + NULL, 0 ); - sandbox_cfg_allow_stat64_filename_array(&cfg, 2, + sandbox_cfg_allow_stat64_filename_array(&cfg, get_datadir_fname("keys"), 1, - get_datadir_fname("stats/dirreq-stats"), 1 + get_datadir_fname("stats/dirreq-stats"), 1, + NULL, 0 ); } From f93ba9a2ef182faf1d9faacf26012135eb999ccf Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 29 Aug 2013 15:44:01 +0300 Subject: [PATCH 52/81] documentation update for _array functions --- src/common/sandbox.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 2c0eb30b8b..51449ca415 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -119,11 +119,10 @@ int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, /** Function used to add a series of open allowed filenames to a supplied * configuration. * @param cfg sandbox configuration. - * @param num number of files. * @param ... all future parameters are specified as pairs of <(char*), 1 / 0> * the char* specifies the path to the allowed file, 1 tells the function * that the char* needs to be free-ed, 0 means the pointer does not need to - * be free-ed. + * be free-ed; the final parameter needs to be . */ int sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...); @@ -139,11 +138,10 @@ int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, /** Function used to add a series of openat allowed filenames to a supplied * configuration. * @param cfg sandbox configuration. - * @param num number of files. * @param ... all future parameters are specified as pairs of <(char*), 1 / 0> * the char* specifies the path to the allowed file, 1 tells the function * that the char* needs to be free-ed, 0 means the pointer does not need to - * be free-ed. + * be free-ed; the final parameter needs to be . */ int sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...); @@ -158,11 +156,10 @@ int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com); /** Function used to add a series of execve allowed filenames to a supplied * configuration. * @param cfg sandbox configuration. - * @param num number of files. * @param ... all future parameters are specified as pairs of <(char*), 1 / 0> * the char* specifies the path to the allowed file, 1 tells the function * that the char* needs to be free-ed, 0 means the pointer does not need to - * be free-ed. + * be free-ed; the final parameter needs to be . */ int sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...); @@ -178,11 +175,10 @@ int sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, /** Function used to add a series of stat64 allowed filenames to a supplied * configuration. * @param cfg sandbox configuration. - * @param num number of files. * @param ... all future parameters are specified as pairs of <(char*), 1 / 0> * the char* specifies the path to the allowed file, 1 tells the function * that the char* needs to be free-ed, 0 means the pointer does not need to - * be free-ed. + * be free-ed; the final parameter needs to be . */ int sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, ...); From 1118bd99108d3ab3404fadfa7eb8e01616836d71 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 29 Aug 2013 16:51:05 +0300 Subject: [PATCH 53/81] switched from multiple mmap to one --- src/common/sandbox.c | 87 +++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 49c057c2aa..4fd95f06d0 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -678,36 +678,65 @@ sandbox_intern_string(const char *param) return param; } -static char* -prot_strdup(char* str) -{ - int param_size = 0; - char *res = NULL; +static int +prot_strings(sandbox_cfg_t* cfg) { + int ret = 0; + int pr_mem_size = 0, pr_mem_left = 0; + char *pr_mem_next = NULL, *pr_mem_base; + sandbox_cfg_t *el = NULL; - if (str == NULL) - goto out; + // get total number of bytes required to mmap + for(el = cfg; el != NULL; el = el->next) { + pr_mem_size += strlen((char*) el->param) + 1; + } - // allocating protected memory region for parameter - param_size = 1 + strlen(str); - - res = (char*) mmap(NULL, param_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | - MAP_ANON, -1, 0); - if (!res) { - log_err(LD_BUG,"(Sandbox) failed allocate protected memory!"); + // allocate protected memory + pr_mem_base = (char*) mmap(NULL, pr_mem_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (pr_mem_base == MAP_FAILED) { + log_err(LD_BUG,"(Sandbox) failed allocate protected memory! mmap: %s", + strerror(errno)); + ret = -1; goto out; } - // copying from non protected to protected + pointer reassign - memcpy(res, str, param_size); + pr_mem_next = pr_mem_base; + pr_mem_left = pr_mem_size; + + // change el value pointer to protected + for (el = cfg; el != NULL; el = el->next) { + char *param_val = (char*) el->param; + int param_size = strlen(param_val) + 1; + + if (pr_mem_left - param_size >= 0) { + // copy to protected + memcpy(pr_mem_next, param_val, param_size); + + // re-point el parameter to protected + free((char*) el->param); + el->param = (intptr_t) pr_mem_next; + el->prot = 1; + + // move next available protected memory + pr_mem_next += param_size; + pr_mem_left -= param_size; + } else { + log_err(LD_BUG,"(Sandbox) insufficient protected memory!"); + ret = -2; + goto out; + } + } // protecting from writes - if (mprotect(res, param_size, PROT_READ)) { - log_err(LD_BUG,"(Sandbox) failed to protect memory!"); - return NULL; + if (mprotect(pr_mem_base, pr_mem_size, PROT_READ)) { + log_err(LD_BUG,"(Sandbox) failed to protect memory! mprotect: %s", + strerror(errno)); + ret = -3; + goto out; } out: - return res; + return ret; } #ifdef __NR_stat64 @@ -719,8 +748,8 @@ sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, int fr) elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); elem->syscall = SCMP_SYS(stat64); elem->pindex = 0; - elem->param = (intptr_t) prot_strdup((char*) file); - elem->prot = 1; + elem->param = (intptr_t) strdup(file); + elem->prot = 0; elem->next = *cfg; *cfg = elem; @@ -763,8 +792,8 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, int fr) elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); elem->syscall = SCMP_SYS(open); elem->pindex = 0; - elem->param = (intptr_t) prot_strdup((char*) file); - elem->prot = 1; + elem->param = (intptr_t) strdup(file); + elem->prot = 0; elem->next = *cfg; *cfg = elem; @@ -806,8 +835,8 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, int fr) elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); elem->syscall = SCMP_SYS(openat); elem->pindex = 1; - elem->param = (intptr_t) prot_strdup((char*) file);; - elem->prot = 1; + elem->param = (intptr_t) strdup(file); + elem->prot = 0; elem->next = *cfg; *cfg = elem; @@ -849,8 +878,8 @@ sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com) elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); elem->syscall = SCMP_SYS(openat); elem->pindex = 1; - elem->param = (intptr_t) prot_strdup((char*) com);; - elem->prot = 1; + elem->param = (intptr_t) strdup(com); + elem->prot = 0; elem->next = *cfg; *cfg = elem; @@ -1121,7 +1150,7 @@ initialise_libseccomp_sandbox(sandbox_cfg_t* cfg) if (install_sigsys_debugging()) return -1; - if (init_addrinfo()) { + if (init_addrinfo() || prot_strings(cfg)) { return -4; } From 3e803a1f18aa04c69e18652f84bf054841706eea Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 29 Aug 2013 16:53:12 +0300 Subject: [PATCH 54/81] make check-spaces fix --- src/common/sandbox.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 4fd95f06d0..748141cda3 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -679,14 +679,15 @@ sandbox_intern_string(const char *param) } static int -prot_strings(sandbox_cfg_t* cfg) { +prot_strings(sandbox_cfg_t* cfg) +{ int ret = 0; int pr_mem_size = 0, pr_mem_left = 0; char *pr_mem_next = NULL, *pr_mem_base; sandbox_cfg_t *el = NULL; // get total number of bytes required to mmap - for(el = cfg; el != NULL; el = el->next) { + for (el = cfg; el != NULL; el = el->next) { pr_mem_size += strlen((char*) el->param) + 1; } @@ -768,7 +769,7 @@ sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, ...) va_list ap; va_start(ap, cfg); - while((fn = va_arg(ap, char*)) != NULL) { + while ((fn = va_arg(ap, char*)) != NULL) { int fr = va_arg(ap, int); rc = sandbox_cfg_allow_stat64_filename(cfg, fn, fr); @@ -812,7 +813,7 @@ sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...) va_list ap; va_start(ap, cfg); - while((fn = va_arg(ap, char*)) != NULL) { + while ((fn = va_arg(ap, char*)) != NULL) { int fr = va_arg(ap, int); rc = sandbox_cfg_allow_open_filename(cfg, fn, fr); @@ -855,7 +856,7 @@ sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...) va_list ap; va_start(ap, cfg); - while((fn = va_arg(ap, char*)) != NULL) { + while ((fn = va_arg(ap, char*)) != NULL) { int fr = va_arg(ap, int); rc = sandbox_cfg_allow_openat_filename(cfg, fn, fr); @@ -896,7 +897,7 @@ sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) va_list ap; va_start(ap, cfg); - while((fn = va_arg(ap, char*)) != NULL) { + while ((fn = va_arg(ap, char*)) != NULL) { rc = sandbox_cfg_allow_execve(cfg, fn); if (rc) { From 1ef0b2e1a37878ebbc29b03fefb214b7501656a6 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 2 Sep 2013 11:44:04 +0300 Subject: [PATCH 55/81] changed how sb getaddrinfo works such that it supports storing multiple results --- src/common/sandbox.c | 66 +++++++++++++++++++++++--------------------- src/common/sandbox.h | 18 ++++++++++++ src/or/main.c | 11 ++++++++ 3 files changed, 63 insertions(+), 32 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 748141cda3..41c3b44d78 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -54,8 +54,7 @@ #include static sandbox_cfg_t *filter_dynamic = NULL; - -static struct addrinfo *sb_addr_info= NULL; +static sb_addr_info_t *sb_addr_info = NULL; /** Variable used for storing all syscall numbers that will be allowed with the * stage 1 general Tor sandbox. @@ -914,54 +913,57 @@ sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) int sandbox_getaddrinfo(const char *name, struct addrinfo **res) { - char hname[256]; + sb_addr_info_t *el; - if (!res) { - return -2; - } *res = NULL; - *res = (struct addrinfo *)malloc(sizeof(struct addrinfo)); - if (*res == NULL) { - return -2; + + for (el = sb_addr_info; el; el = el->next) { + if(!strcmp(el->name, name)) { + *res = (struct addrinfo *)malloc(sizeof(struct addrinfo)); + if (!res) { + return -2; + } + + memcpy(*res, el->info, sizeof(struct addrinfo)); + + return 0; + } } - if (gethostname(hname, sizeof(hname)) < 0) { - return -1; - } - - if (strcmp(name, hname) || sb_addr_info == NULL) { - log_err(LD_BUG,"(Sandbox) failed for hname %s!", name); - return -1; - } - - memcpy(*res, sb_addr_info, sizeof(struct addrinfo)); - return 0; + return -1; } -static int -init_addrinfo(void) +int +sandbox_add_addrinfo(const char* name) { int ret; struct addrinfo hints; - char hname[256]; + sb_addr_info_t *el = NULL; - sb_addr_info = NULL; - - if (gethostname(hname, sizeof(hname)) < 0) { - return -1; + el = (sb_addr_info_t*) malloc(sizeof(sb_addr_info_t)); + if(!el) { + log_err(LD_BUG,"(Sandbox) failed to allocate addr info!"); + ret = -2; + goto out; } memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; - ret = getaddrinfo(hname, NULL, &hints, &sb_addr_info); + ret = getaddrinfo(name, NULL, &hints, &(el->info)); if (ret) { - sb_addr_info = NULL; - return -2; + log_err(LD_BUG,"(Sandbox) failed to getaddrinfo"); + ret = -2; + goto out; } - return 0; + el->name = strdup(name); + el->next = sb_addr_info; + sb_addr_info = el; + + out: + return ret; } static int @@ -1151,7 +1153,7 @@ initialise_libseccomp_sandbox(sandbox_cfg_t* cfg) if (install_sigsys_debugging()) return -1; - if (init_addrinfo() || prot_strings(cfg)) { + if (prot_strings(cfg)) { return -4; } diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 51449ca415..9a61749a3f 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -62,6 +62,21 @@ struct pfd_elem { /** Typedef to structure used to manage a sandbox configuration. */ typedef struct pfd_elem sandbox_cfg_t; +/** + * Structure used for keeping a linked list of getaddrinfo pre-recorded + * results. + */ +struct sb_addr_info_el { + /** Name of the address info result. */ + char *name; + /** Pre-recorded getaddrinfo result. */ + struct addrinfo *info; + /** Next element in the list. */ + struct sb_addr_info_el *next; +}; +/** Typedef to structure used to manage an addrinfo list. */ +typedef struct sb_addr_info_el sb_addr_info_t; + /** Function pointer defining the prototype of a filter function.*/ typedef int (*sandbox_filter_func_t)(scmp_filter_ctx ctx, sandbox_cfg_t *filter); @@ -93,6 +108,9 @@ typedef struct { #endif // __linux__ +/** Pre-calls getaddrinfo in order to pre-record result. */ +int sandbox_add_addrinfo(const char *addr); + /** Replacement for getaddrinfo(), using pre-recorded results. */ int sandbox_getaddrinfo(const char *name, struct addrinfo **res); diff --git a/src/or/main.c b/src/or/main.c index 861f586c90..af05f0b71a 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2639,6 +2639,15 @@ find_flashcard_path(PWCHAR path, size_t size) } #endif +static void +init_addrinfo(void) { + char hname[256]; + + // host name to sandbox + gethostname(hname, sizeof(hname)); + sandbox_add_addrinfo(hname); +} + static sandbox_cfg_t* sandbox_init_filter() { @@ -2713,6 +2722,8 @@ sandbox_init_filter() sandbox_cfg_allow_execve(&cfg, "/usr/local/bin/tor"); + init_addrinfo(); + return cfg; } From c584537a038cdeede4d52b52a73dcbb3035112a4 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 2 Sep 2013 11:45:09 +0300 Subject: [PATCH 56/81] make check-spaces fix --- src/common/sandbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 41c3b44d78..a4919121cf 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -918,7 +918,7 @@ sandbox_getaddrinfo(const char *name, struct addrinfo **res) *res = NULL; for (el = sb_addr_info; el; el = el->next) { - if(!strcmp(el->name, name)) { + if (!strcmp(el->name, name)) { *res = (struct addrinfo *)malloc(sizeof(struct addrinfo)); if (!res) { return -2; @@ -941,7 +941,7 @@ sandbox_add_addrinfo(const char* name) sb_addr_info_t *el = NULL; el = (sb_addr_info_t*) malloc(sizeof(sb_addr_info_t)); - if(!el) { + if (!el) { log_err(LD_BUG,"(Sandbox) failed to allocate addr info!"); ret = -2; goto out; From fe6e2733ab1e75e0b56741fa06094b257b3695b8 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 2 Sep 2013 12:16:02 +0300 Subject: [PATCH 57/81] added contingency message to test for sandbox_getaddrinfo --- src/common/sandbox.c | 3 ++- src/or/main.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index a4919121cf..84d21833bb 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -930,6 +930,7 @@ sandbox_getaddrinfo(const char *name, struct addrinfo **res) } } + log_err(LD_BUG,"(Sandbox) failed to get address %s!", name); return -1; } @@ -958,7 +959,7 @@ sandbox_add_addrinfo(const char* name) goto out; } - el->name = strdup(name); + el->name = tor_strdup(name); el->next = sb_addr_info; sb_addr_info = el; diff --git a/src/or/main.c b/src/or/main.c index af05f0b71a..5ab49365b0 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2640,7 +2640,8 @@ find_flashcard_path(PWCHAR path, size_t size) #endif static void -init_addrinfo(void) { +init_addrinfo(void) +{ char hname[256]; // host name to sandbox From b4b0eddd29b0b2ad78e4cf61362283034677f42f Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 2 Sep 2013 13:54:43 +0300 Subject: [PATCH 58/81] switched to a more generic way of handling the sandbox configuration --- src/common/sandbox.c | 119 ++++++++++++++++++++++++++++--------------- src/common/sandbox.h | 37 +++++++++++--- 2 files changed, 107 insertions(+), 49 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 84d21833bb..1f0584cce1 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -24,6 +24,7 @@ #include "orconfig.h" #include "torint.h" #include "util.h" +#include "tor_queue.h" #if defined(HAVE_SECCOMP_H) && defined(__linux__) #define USE_LIBSECCOMP @@ -156,9 +157,12 @@ sb_execve(scmp_filter_ctx ctx, sandbox_cfg_t *filter) // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { - if (elem->prot == 1 && elem->syscall == SCMP_SYS(execve)) { + smp_param_t *param = (smp_param_t*) elem->param; + + if (param != NULL && param->prot == 1 && param->syscall + == SCMP_SYS(execve)) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), 1, - SCMP_CMP(0, SCMP_CMP_EQ, elem->param)); + SCMP_CMP(0, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add execve syscall, received " "libseccomp error %d", rc); @@ -266,9 +270,12 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { - if (elem->prot == 1 && elem->syscall == SCMP_SYS(open)) { + smp_param_t *param = elem->param; + + if (param != NULL && param->prot == 1 && param->syscall + == SCMP_SYS(open)) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, - SCMP_CMP(0, SCMP_CMP_EQ, elem->param)); + SCMP_CMP(0, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " "libseccomp error %d", rc); @@ -297,10 +304,13 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { - if (elem->prot == 1 && elem->syscall == SCMP_SYS(openat)) { + smp_param_t *param = elem->param; + + if (param != NULL && param->prot == 1 && param->syscall + == SCMP_SYS(openat)) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 1, SCMP_CMP(0, SCMP_CMP_EQ, AT_FDCWD), - SCMP_CMP(1, SCMP_CMP_EQ, elem->param), + SCMP_CMP(1, SCMP_CMP_EQ, param->value), SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY| O_CLOEXEC)); if (rc != 0) { @@ -618,10 +628,12 @@ sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { - if (elem->prot == 1 && (elem->syscall == SCMP_SYS(open) || - elem->syscall == SCMP_SYS(stat64))) { + smp_param_t *param = elem->param; + + if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open) + || param->syscall == SCMP_SYS(stat64))) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64), 1, - SCMP_CMP(0, SCMP_CMP_EQ, elem->param)); + SCMP_CMP(0, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " "libseccomp error %d", rc); @@ -660,21 +672,23 @@ static sandbox_filter_func_t filter_func[] = { }; const char* -sandbox_intern_string(const char *param) +sandbox_intern_string(const char *str) { sandbox_cfg_t *elem; - if (param == NULL) + if (str == NULL) return NULL; for (elem = filter_dynamic; elem != NULL; elem = elem->next) { - if (elem->prot && !strcmp(param, (char*)(elem->param))) { - return (char*)(elem->param); + smp_param_t *param = elem->param; + + if (param->prot && !strcmp(str, (char*)(param->value))) { + return (char*)(param->value); } } - log_info(LD_GENERAL, "(Sandbox) Parameter %s not found", param); - return param; + log_info(LD_GENERAL, "(Sandbox) Parameter %s not found", str); + return str; } static int @@ -687,7 +701,7 @@ prot_strings(sandbox_cfg_t* cfg) // get total number of bytes required to mmap for (el = cfg; el != NULL; el = el->next) { - pr_mem_size += strlen((char*) el->param) + 1; + pr_mem_size += strlen((char*) ((smp_param_t*)el->param)->value) + 1; } // allocate protected memory @@ -705,7 +719,7 @@ prot_strings(sandbox_cfg_t* cfg) // change el value pointer to protected for (el = cfg; el != NULL; el = el->next) { - char *param_val = (char*) el->param; + char *param_val = (char*)((smp_param_t *)el->param)->value; int param_size = strlen(param_val) + 1; if (pr_mem_left - param_size >= 0) { @@ -713,9 +727,9 @@ prot_strings(sandbox_cfg_t* cfg) memcpy(pr_mem_next, param_val, param_size); // re-point el parameter to protected - free((char*) el->param); - el->param = (intptr_t) pr_mem_next; - el->prot = 1; + free((char*) ((smp_param_t*)el->param)->value); + ((smp_param_t*)el->param)->value = (intptr_t) pr_mem_next; + ((smp_param_t*)el->param)->prot = 1; // move next available protected memory pr_mem_next += param_size; @@ -739,23 +753,46 @@ prot_strings(sandbox_cfg_t* cfg) return ret; } +static sandbox_cfg_t* +new_element(int syscall, int index, intptr_t value) +{ + smp_param_t *param = NULL; + + sandbox_cfg_t *elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); + if (!elem) + return NULL; + + elem->param = (smp_param_t*) malloc(sizeof(smp_param_t)); + if (!elem->param) { + free(elem); + return NULL; + } + + param = elem->param; + param->syscall = syscall; + param->pindex = index; + param->value = value; + param->prot = 0; + + return elem; +} + #ifdef __NR_stat64 int sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; - elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); - elem->syscall = SCMP_SYS(stat64); - elem->pindex = 0; - elem->param = (intptr_t) strdup(file); - elem->prot = 0; + elem = new_element(SCMP_SYS(stat64), 0, (intptr_t) strdup(file)); + if (!elem) { + log_err(LD_BUG,"(Sandbox) failed to register parameter!"); + return -1; + } elem->next = *cfg; *cfg = elem; if (fr) tor_free_(file); - return 0; } @@ -789,11 +826,11 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; - elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); - elem->syscall = SCMP_SYS(open); - elem->pindex = 0; - elem->param = (intptr_t) strdup(file); - elem->prot = 0; + elem = new_element(SCMP_SYS(open), 0, (intptr_t) strdup(file)); + if (!elem) { + log_err(LD_BUG,"(Sandbox) failed to register parameter!"); + return -1; + } elem->next = *cfg; *cfg = elem; @@ -832,11 +869,11 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; - elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); - elem->syscall = SCMP_SYS(openat); - elem->pindex = 1; - elem->param = (intptr_t) strdup(file); - elem->prot = 0; + elem = new_element(SCMP_SYS(openat), 1, (intptr_t) strdup(file)); + if (!elem) { + log_err(LD_BUG,"(Sandbox) failed to register parameter!"); + return -1; + } elem->next = *cfg; *cfg = elem; @@ -875,11 +912,11 @@ sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com) { sandbox_cfg_t *elem = NULL; - elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); - elem->syscall = SCMP_SYS(openat); - elem->pindex = 1; - elem->param = (intptr_t) strdup(com); - elem->prot = 0; + elem = new_element(SCMP_SYS(execve), 1, (intptr_t) strdup(com)); + if (!elem) { + log_err(LD_BUG,"(Sandbox) failed to register parameter!"); + return -1; + } elem->next = *cfg; *cfg = elem; diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 9a61749a3f..59474c4fe8 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -40,27 +40,48 @@ #define PARAM_NUM 1 /** - * Structure used to manage a sandbox configuration. - * - * It is implemented as a linked list of parameters. Currently only controls - * parameters for open, openat, execve, stat64. + * Enum used to manage the type of the implementation for general purpose. */ -struct pfd_elem { +typedef enum { + /** Libseccomp implementation based on seccomp2*/ + LIBSECCOMP2 = 0 +} SB_IMPL; + +/** + * Configuration parameter structure associated with the LIBSECCOMP2 + * implementation. + */ +typedef struct smp_param { /** syscall associated with parameter. */ int syscall; /** parameter index. */ int pindex; /** parameter value. */ - intptr_t param; + intptr_t value; /** parameter flag (0 = not protected, 1 = protected). */ int prot; +} smp_param_t; - struct pfd_elem *next; +/** + * Structure used to manage a sandbox configuration. + * + * It is implemented as a linked list of parameters. Currently only controls + * parameters for open, openat, execve, stat64. + */ +struct sandbox_cfg_elem { + /** Sandbox implementation which dictates the parameter type. */ + SB_IMPL implem; + + /** Configuration parameter. */ + void *param; + + /** Next element of the configuration*/ + struct sandbox_cfg_elem *next; }; /** Typedef to structure used to manage a sandbox configuration. */ -typedef struct pfd_elem sandbox_cfg_t; +typedef struct sandbox_cfg_elem sandbox_cfg_t; /** * Structure used for keeping a linked list of getaddrinfo pre-recorded From 55d8b8e578e17d8654f33f62fdc4a4419a6b92a7 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 3 Sep 2013 16:37:12 +0300 Subject: [PATCH 59/81] fixed bug where sandbox_getaddrinfo() would fail when -Sandbox is 0 --- src/common/address.c | 2 +- src/common/sandbox.c | 30 ++++++++++++++++++++++++++---- src/common/sandbox.h | 3 ++- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/common/address.c b/src/common/address.c index 5c8603ee20..a46aeb0d45 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -235,7 +235,7 @@ tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr) memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; - err = sandbox_getaddrinfo(name, &res); + err = sandbox_getaddrinfo(name, hints, &res); if (!err) { best = NULL; for (res_p = res; res_p; res_p = res_p->ai_next) { diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 1f0584cce1..19c28981ed 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -54,6 +54,7 @@ #include #include +static int sandbox_active = 0; static sandbox_cfg_t *filter_dynamic = NULL; static sb_addr_info_t *sb_addr_info = NULL; @@ -948,7 +949,8 @@ sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) } int -sandbox_getaddrinfo(const char *name, struct addrinfo **res) +sandbox_getaddrinfo(const char *name, struct addrinfo hints, + struct addrinfo **res) { sb_addr_info_t *el; @@ -956,18 +958,31 @@ sandbox_getaddrinfo(const char *name, struct addrinfo **res) for (el = sb_addr_info; el; el = el->next) { if (!strcmp(el->name, name)) { - *res = (struct addrinfo *)malloc(sizeof(struct addrinfo)); + *res = (struct addrinfo *) malloc(sizeof(struct addrinfo)); if (!res) { return -2; } memcpy(*res, el->info, sizeof(struct addrinfo)); - return 0; } } + if (!sandbox_active) { + if (getaddrinfo(name, NULL, &hints, res)) { + log_err(LD_BUG,"(Sandbox) getaddrinfo failed!"); + return -1; + } + + return 0; + } + + // getting here means something went wrong log_err(LD_BUG,"(Sandbox) failed to get address %s!", name); + if (*res) { + free(*res); + res = NULL; + } return -1; } @@ -1069,7 +1084,14 @@ install_syscall_filter(sandbox_cfg_t* cfg) goto end; } - rc = seccomp_load(ctx); + // loading the seccomp2 filter + if((rc = seccomp_load(ctx))) { + log_err(LD_BUG, "(Sandbox) failed to load!"); + goto end; + } + + // marking the sandbox as active + sandbox_active = 1; end: seccomp_release(ctx); diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 59474c4fe8..503bb70846 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -133,7 +133,8 @@ typedef struct { int sandbox_add_addrinfo(const char *addr); /** Replacement for getaddrinfo(), using pre-recorded results. */ -int sandbox_getaddrinfo(const char *name, struct addrinfo **res); +int sandbox_getaddrinfo(const char *name, struct addrinfo hints, + struct addrinfo **res); /** Use fd to log non-survivable sandbox violations. */ void sandbox_set_debugging_fd(int fd); From 42f5737c810622bd1e83caffd27c25908e862597 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Fri, 6 Sep 2013 12:26:50 +0300 Subject: [PATCH 60/81] switched string lengths from int to size_t in prot_strings() --- src/common/sandbox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 19c28981ed..b4189b5df6 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -696,7 +696,7 @@ static int prot_strings(sandbox_cfg_t* cfg) { int ret = 0; - int pr_mem_size = 0, pr_mem_left = 0; + size_t pr_mem_size = 0, pr_mem_left = 0; char *pr_mem_next = NULL, *pr_mem_base; sandbox_cfg_t *el = NULL; @@ -721,7 +721,7 @@ prot_strings(sandbox_cfg_t* cfg) // change el value pointer to protected for (el = cfg; el != NULL; el = el->next) { char *param_val = (char*)((smp_param_t *)el->param)->value; - int param_size = strlen(param_val) + 1; + size_t param_size = strlen(param_val) + 1; if (pr_mem_left - param_size >= 0) { // copy to protected From 2a6c34750d1723382e0342333ef9a15785adaf66 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Fri, 6 Sep 2013 12:29:15 +0300 Subject: [PATCH 61/81] replaced malloc/free with tor_malloc/tor_free --- src/common/sandbox.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index b4189b5df6..0c2145f846 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -728,7 +728,7 @@ prot_strings(sandbox_cfg_t* cfg) memcpy(pr_mem_next, param_val, param_size); // re-point el parameter to protected - free((char*) ((smp_param_t*)el->param)->value); + tor_free((char*) ((smp_param_t*)el->param)->value); ((smp_param_t*)el->param)->value = (intptr_t) pr_mem_next; ((smp_param_t*)el->param)->prot = 1; @@ -759,13 +759,13 @@ new_element(int syscall, int index, intptr_t value) { smp_param_t *param = NULL; - sandbox_cfg_t *elem = (sandbox_cfg_t*) malloc(sizeof(sandbox_cfg_t)); + sandbox_cfg_t *elem = (sandbox_cfg_t*) tor_malloc(sizeof(sandbox_cfg_t)); if (!elem) return NULL; - elem->param = (smp_param_t*) malloc(sizeof(smp_param_t)); + elem->param = (smp_param_t*) tor_malloc(sizeof(smp_param_t)); if (!elem->param) { - free(elem); + tor_free(elem); return NULL; } @@ -793,7 +793,7 @@ sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, int fr) elem->next = *cfg; *cfg = elem; - if (fr) tor_free_(file); + if (fr) tor_free(file); return 0; } @@ -836,7 +836,7 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, int fr) elem->next = *cfg; *cfg = elem; - if (fr) tor_free_(file); + if (fr) tor_free(file); return 0; } @@ -879,7 +879,7 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, int fr) elem->next = *cfg; *cfg = elem; - if (fr) tor_free_(file); + if (fr) tor_free(file); return 0; } @@ -958,7 +958,7 @@ sandbox_getaddrinfo(const char *name, struct addrinfo hints, for (el = sb_addr_info; el; el = el->next) { if (!strcmp(el->name, name)) { - *res = (struct addrinfo *) malloc(sizeof(struct addrinfo)); + *res = (struct addrinfo *) tor_malloc(sizeof(struct addrinfo)); if (!res) { return -2; } @@ -980,7 +980,7 @@ sandbox_getaddrinfo(const char *name, struct addrinfo hints, // getting here means something went wrong log_err(LD_BUG,"(Sandbox) failed to get address %s!", name); if (*res) { - free(*res); + tor_free(*res); res = NULL; } return -1; @@ -993,7 +993,7 @@ sandbox_add_addrinfo(const char* name) struct addrinfo hints; sb_addr_info_t *el = NULL; - el = (sb_addr_info_t*) malloc(sizeof(sb_addr_info_t)); + el = (sb_addr_info_t*) tor_malloc(sizeof(sb_addr_info_t)); if (!el) { log_err(LD_BUG,"(Sandbox) failed to allocate addr info!"); ret = -2; From 839ff0063d3fca10a64abf69ab27d1fd88456889 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Fri, 6 Sep 2013 12:30:01 +0300 Subject: [PATCH 62/81] replaced strdup with tor_strdup --- src/common/sandbox.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 0c2145f846..7e77ea1766 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -784,7 +784,7 @@ sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(stat64), 0, (intptr_t) strdup(file)); + elem = new_element(SCMP_SYS(stat64), 0, (intptr_t) tor_strdup(file)); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -827,7 +827,7 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(open), 0, (intptr_t) strdup(file)); + elem = new_element(SCMP_SYS(open), 0, (intptr_t) tor_strdup(file)); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -870,7 +870,7 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(openat), 1, (intptr_t) strdup(file)); + elem = new_element(SCMP_SYS(openat), 1, (intptr_t) tor_strdup(file)); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -913,7 +913,7 @@ sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(execve), 1, (intptr_t) strdup(com)); + elem = new_element(SCMP_SYS(execve), 1, (intptr_t) tor_strdup(com)); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; From 6a22b29641834cecb446282588f9d47d8678b8b4 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Fri, 6 Sep 2013 12:39:56 +0300 Subject: [PATCH 63/81] passing hints as a const pointer to sandbox_getaddrinfo(), also one tor_free macro fails to compile.. --- src/common/address.c | 2 +- src/common/sandbox.c | 6 +++--- src/common/sandbox.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/common/address.c b/src/common/address.c index a46aeb0d45..f9647b9a90 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -235,7 +235,7 @@ tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr) memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; - err = sandbox_getaddrinfo(name, hints, &res); + err = sandbox_getaddrinfo(name, &hints, &res); if (!err) { best = NULL; for (res_p = res; res_p; res_p = res_p->ai_next) { diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 7e77ea1766..e936b62135 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -728,7 +728,7 @@ prot_strings(sandbox_cfg_t* cfg) memcpy(pr_mem_next, param_val, param_size); // re-point el parameter to protected - tor_free((char*) ((smp_param_t*)el->param)->value); + free((char*)((smp_param_t*)el->param)->value); ((smp_param_t*)el->param)->value = (intptr_t) pr_mem_next; ((smp_param_t*)el->param)->prot = 1; @@ -949,7 +949,7 @@ sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) } int -sandbox_getaddrinfo(const char *name, struct addrinfo hints, +sandbox_getaddrinfo(const char *name, const struct addrinfo *hints, struct addrinfo **res) { sb_addr_info_t *el; @@ -969,7 +969,7 @@ sandbox_getaddrinfo(const char *name, struct addrinfo hints, } if (!sandbox_active) { - if (getaddrinfo(name, NULL, &hints, res)) { + if (getaddrinfo(name, NULL, hints, res)) { log_err(LD_BUG,"(Sandbox) getaddrinfo failed!"); return -1; } diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 503bb70846..ed9caa1686 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -133,7 +133,7 @@ typedef struct { int sandbox_add_addrinfo(const char *addr); /** Replacement for getaddrinfo(), using pre-recorded results. */ -int sandbox_getaddrinfo(const char *name, struct addrinfo hints, +int sandbox_getaddrinfo(const char *name, const struct addrinfo *hints, struct addrinfo **res); /** Use fd to log non-survivable sandbox violations. */ From 340cca524f23195c00c46874b19980bbe7138ead Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Fri, 6 Sep 2013 21:41:45 +0300 Subject: [PATCH 64/81] added missing documentation for sandbox functions --- src/common/sandbox.c | 157 +++++++++++++++++++++++++++++++++---------- 1 file changed, 121 insertions(+), 36 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index e936b62135..1fa4d613c1 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -54,8 +54,11 @@ #include #include +/**Determines if at least one sandbox is active.*/ static int sandbox_active = 0; +/** Holds the parameter list configuration for the sandbox.*/ static sandbox_cfg_t *filter_dynamic = NULL; +/** Holds a list of pre-recorded results from getaddrinfo().*/ static sb_addr_info_t *sb_addr_info = NULL; /** Variable used for storing all syscall numbers that will be allowed with the @@ -130,6 +133,10 @@ static int filter_nopar_gen[] = { SCMP_SYS(unlink) }; +/** + * Function responsible for setting up the rt_sigaction syscall for + * the seccomp filter sandbox. + */ static int sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -150,6 +157,10 @@ sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return rc; } +/** + * Function responsible for setting up the execve syscall for + * the seccomp filter sandbox. + */ static int sb_execve(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -175,6 +186,10 @@ sb_execve(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +/** + * Function responsible for setting up the time syscall for + * the seccomp filter sandbox. + */ static int sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -182,6 +197,10 @@ sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter) SCMP_CMP(0, SCMP_CMP_EQ, 0)); } +/** + * Function responsible for setting up the accept4 syscall for + * the seccomp filter sandbox. + */ static int sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -205,6 +224,10 @@ sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } #ifdef __NR_mmap2 +/** + * Function responsible for setting up the mmap2 syscall for + * the seccomp filter sandbox. + */ static int sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -263,6 +286,10 @@ sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } #endif +/** + * Function responsible for setting up the open syscall for + * the seccomp filter sandbox. + */ static int sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -285,7 +312,6 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } } - // problem: required by getaddrinfo rc = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(-1), SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_EQ, O_RDONLY|O_CLOEXEC)); if (rc != 0) { @@ -297,6 +323,10 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +/** + * Function responsible for setting up the openat syscall for + * the seccomp filter sandbox. + */ static int sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -325,6 +355,10 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +/** + * Function responsible for setting up the socket syscall for + * the seccomp filter sandbox. + */ static int sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -367,6 +401,10 @@ sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +/** + * Function responsible for setting up the socketpair syscall for + * the seccomp filter sandbox. + */ static int sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -387,6 +425,10 @@ sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +/** + * Function responsible for setting up the setsockopt syscall for + * the seccomp filter sandbox. + */ static int sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -407,6 +449,10 @@ sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +/** + * Function responsible for setting up the getsockopt syscall for + * the seccomp filter sandbox. + */ static int sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -428,6 +474,10 @@ sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } #ifdef __NR_fcntl64 +/** + * Function responsible for setting up the fcntl64 syscall for + * the seccomp filter sandbox. + */ static int sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -459,7 +509,12 @@ sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } #endif -// allows everything but will keep for now.. +/** + * Function responsible for setting up the epoll_ctl syscall for + * the seccomp filter sandbox. + * + * Note: basically allows everything but will keep for now.. + */ static int sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -484,8 +539,11 @@ sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } /** - * If multiple filters need to be added, seccomp needs to be whitelisted in - * this list. + * Function responsible for setting up the fcntl64 syscall for + * the seccomp filter sandbox. + * + * NOTE: if multiple filters need to be added, the PR_SECCOMP parameter needs + * to be whitelisted in this function. */ static int sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) @@ -501,7 +559,11 @@ sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } /** - * does not NEED tobe here.. only occurs before filter + * Function responsible for setting up the fcntl64 syscall for + * the seccomp filter sandbox. + * + * NOTE: does not NEED to be here.. currently only occurs before filter; will + * keep just in case for the future. */ static int sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter) @@ -526,6 +588,10 @@ sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +/** + * Function responsible for setting up the rt_sigprocmask syscall for + * the seccomp filter sandbox. + */ static int sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -545,7 +611,10 @@ sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } /** - * does not NEED tobe here.. only occurs before filter + * Function responsible for setting up the flock syscall for + * the seccomp filter sandbox. + * + * NOTE: does not need to be here, occurs before filter is applied. */ static int sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter) @@ -565,6 +634,10 @@ sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +/** + * Function responsible for setting up the futex syscall for + * the seccomp filter sandbox. + */ static int sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -591,7 +664,10 @@ sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } /** - * does not NEED tobe here.. only occurs before filter + * Function responsible for setting up the mremap syscall for + * the seccomp filter sandbox. + * + * NOTE: so far only occurs before filter is applied. */ static int sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter) @@ -606,6 +682,10 @@ sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +/** + * Function responsible for setting up the poll syscall for + * the seccomp filter sandbox. + */ static int sb_poll(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -621,6 +701,10 @@ sb_poll(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } #ifdef __NR_stat64 +/** + * Function responsible for setting up the stat64 syscall for + * the seccomp filter sandbox. + */ static int sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { @@ -647,6 +731,10 @@ sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } #endif +/** + * Array of function pointers responsible for filtering different syscalls at + * a parameter level. + */ static sandbox_filter_func_t filter_func[] = { sb_rt_sigaction, sb_rt_sigprocmask, @@ -692,6 +780,12 @@ sandbox_intern_string(const char *str) return str; } +/** + * Protects all the strings in the sandbox's parameter list configuration. It + * works by calculating the total amount of memory required by the parameter + * list, allocating the memory using mmap, and protecting it from writes with + * mprotect(). + */ static int prot_strings(sandbox_cfg_t* cfg) { @@ -754,6 +848,12 @@ prot_strings(sandbox_cfg_t* cfg) return ret; } +/** + * Auxiliary function used in order to allocate a sandbox_cfg_t element and set + * it's values according the the parameter list. All elements are initialised + * with the 'prot' field set to false, as the pointer is not protected at this + * point. + */ static sandbox_cfg_t* new_element(int syscall, int index, intptr_t value) { @@ -1019,6 +1119,10 @@ sandbox_add_addrinfo(const char* name) return ret; } +/** + * Function responsible for going through the parameter syscall filters and + * call each function pointer in the list. + */ static int add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) { @@ -1036,6 +1140,10 @@ add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) return 0; } +/** + * Function responsible of loading the libseccomp syscall filters which do not + * have parameter filtering. + */ static int add_noparam_filter(scmp_filter_ctx ctx) { @@ -1085,7 +1193,7 @@ install_syscall_filter(sandbox_cfg_t* cfg) } // loading the seccomp2 filter - if((rc = seccomp_load(ctx))) { + if ((rc = seccomp_load(ctx))) { log_err(LD_BUG, "(Sandbox) failed to load!"); goto end; } @@ -1183,6 +1291,11 @@ install_sigsys_debugging(void) return 0; } +/** + * Function responsible of registering the sandbox_cfg_t list of parameter + * syscall filters to the existing parameter list. This is used for incipient + * multiple-sandbox support. + */ static int register_cfg(sandbox_cfg_t* cfg) { @@ -1256,34 +1369,6 @@ sandbox_init(sandbox_cfg_t* cfg) #endif } -/** - * Enables the stage 1 general sandbox. It applies a syscall filter which does - * not restrict any Tor features. The filter is representative for the whole - * application. - */ -int -tor_global_sandbox(void) -{ - -#if defined(USE_LIBSECCOMP) - return initialise_libseccomp_sandbox(NULL); - -#elif defined(_WIN32) - log_warn(LD_BUG,"Windows sandboxing is not implemented. The feature is " - "currently disabled."); - return 0; - -#elif defined(TARGET_OS_MAC) - log_warn(LD_BUG,"Mac OSX sandboxing is not implemented. The feature is " - "currently disabled"); - return 0; -#else - log_warn(LD_BUG,"Sandboxing is not implemented for your platform. The " - "feature is currently disabled"); - return 0; -#endif -} - void sandbox_set_debugging_fd(int fd) { From 00fd0cc5f91ad431c4beb25b8cc8f89ff1462268 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Sep 2013 14:55:47 -0400 Subject: [PATCH 65/81] Basic compilation fixes. --- src/common/sandbox.c | 24 ++++++++++++++++++------ src/common/sandbox.h | 6 +++--- src/or/main.c | 6 +++--- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 1fa4d613c1..2f5859e779 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -118,8 +118,10 @@ static int filter_nopar_gen[] = { SCMP_SYS(exit), SCMP_SYS(madvise), +#ifdef __NR_stat64 // getaddrinfo uses this.. SCMP_SYS(stat64), +#endif // socket syscalls SCMP_SYS(bind), @@ -741,10 +743,14 @@ static sandbox_filter_func_t filter_func[] = { sb_execve, sb_time, sb_accept4, +#ifdef __NR_mmap2 sb_mmap2, +#endif sb_open, sb_openat, +#ifdef __NR_fcntl64 sb_fcntl64, +#endif sb_epoll_ctl, sb_prctl, sb_mprotect, @@ -752,7 +758,9 @@ static sandbox_filter_func_t filter_func[] = { sb_futex, sb_mremap, sb_poll, +#ifdef __NR_stat64 sb_stat64, +#endif sb_socket, sb_setsockopt, @@ -879,12 +887,17 @@ new_element(int syscall, int index, intptr_t value) } #ifdef __NR_stat64 +#define SCMP_stat SCMP_SYS(stat64) +#else +#define SCMP_stat SCMP_SYS(stat) +#endif + int -sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, int fr) +sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(stat64), 0, (intptr_t) tor_strdup(file)); + elem = new_element(SCMP_stat, 0, (intptr_t) tor_strdup(file)); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -898,7 +911,7 @@ sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, int fr) } int -sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, ...) +sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...) { int rc = 0; char *fn = NULL; @@ -909,9 +922,9 @@ sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, ...) while ((fn = va_arg(ap, char*)) != NULL) { int fr = va_arg(ap, int); - rc = sandbox_cfg_allow_stat64_filename(cfg, fn, fr); + rc = sandbox_cfg_allow_stat_filename(cfg, fn, fr); if (rc) { - log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_stat64_filename_array fail"); + log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_stat_filename_array fail"); goto end; } } @@ -920,7 +933,6 @@ sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, ...) va_end(ap); return 0; } -#endif int sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, int fr) diff --git a/src/common/sandbox.h b/src/common/sandbox.h index ed9caa1686..e61e0b3338 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -204,12 +204,12 @@ int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com); int sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...); /** - * Function used to add a stat64 allowed filename to a supplied configuration. + * Function used to add a stat/stat64 allowed filename to a configuration. * The (char*) specifies the path to the allowed file, fr = 1 tells the * function that the char* needs to be free-ed, 0 means the pointer does not * need to be free-ed. */ -int sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, +int sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file, int fr); /** Function used to add a series of stat64 allowed filenames to a supplied @@ -220,7 +220,7 @@ int sandbox_cfg_allow_stat64_filename(sandbox_cfg_t **cfg, char *file, * that the char* needs to be free-ed, 0 means the pointer does not need to * be free-ed; the final parameter needs to be . */ -int sandbox_cfg_allow_stat64_filename_array(sandbox_cfg_t **cfg, ...); +int sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...); /** Function used to initialise a sandbox configuration.*/ int sandbox_init(sandbox_cfg_t* cfg); diff --git a/src/or/main.c b/src/or/main.c index 5ab49365b0..18e8bc44ae 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2650,7 +2650,7 @@ init_addrinfo(void) } static sandbox_cfg_t* -sandbox_init_filter() +sandbox_init_filter(void) { sandbox_cfg_t *cfg = sandbox_cfg_new(); @@ -2685,7 +2685,7 @@ sandbox_init_filter() NULL, 0 ); - sandbox_cfg_allow_stat64_filename_array(&cfg, + sandbox_cfg_allow_stat_filename_array(&cfg, get_datadir_fname(NULL), 1, get_datadir_fname("lock"), 1, get_datadir_fname("state"), 1, @@ -2714,7 +2714,7 @@ sandbox_init_filter() NULL, 0 ); - sandbox_cfg_allow_stat64_filename_array(&cfg, + sandbox_cfg_allow_stat_filename_array(&cfg, get_datadir_fname("keys"), 1, get_datadir_fname("stats/dirreq-stats"), 1, NULL, 0 From 42e6ab0e14bc3f6c71e262b4c9d888f67beb599f Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Sep 2013 14:58:15 -0400 Subject: [PATCH 66/81] Remove a usage of free() --- src/common/sandbox.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 2f5859e779..6fdddd2f2f 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -830,7 +830,10 @@ prot_strings(sandbox_cfg_t* cfg) memcpy(pr_mem_next, param_val, param_size); // re-point el parameter to protected - free((char*)((smp_param_t*)el->param)->value); + { + void *old_val = ((smp_param_t*)el->param)->value; + tor_free(old_val); + } ((smp_param_t*)el->param)->value = (intptr_t) pr_mem_next; ((smp_param_t*)el->param)->prot = 1; From cc35d8be8472ae7ae1ebc3421ff798ec1d893c06 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Sep 2013 15:14:50 -0400 Subject: [PATCH 67/81] Fix most of the --enable-gcc-warnings warnings in the sandbox code --- src/common/sandbox.c | 38 ++++++++++++++++++++++++++++---------- src/common/sandbox.h | 2 +- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 6fdddd2f2f..1fd2119fa2 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -142,12 +142,14 @@ static int filter_nopar_gen[] = { static int sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { - int i, rc; + unsigned i; + int rc; int param[] = { SIGINT, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGCHLD, #ifdef SIGXFSZ SIGXFSZ #endif }; + (void) filter; for (i = 0; i < ARRAY_LENGTH(param); i++) { rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 1, @@ -195,6 +197,7 @@ sb_execve(scmp_filter_ctx ctx, sandbox_cfg_t *filter) static int sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { + (void) filter; return seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time), 1, SCMP_CMP(0, SCMP_CMP_EQ, 0)); } @@ -207,6 +210,7 @@ static int sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void)filter; #ifdef __i386__ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall), 1, @@ -365,6 +369,7 @@ static int sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void) filter; #ifdef __i386__ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0); @@ -411,6 +416,7 @@ static int sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void) filter; #ifdef __i386__ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 0); @@ -435,6 +441,7 @@ static int sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void) filter; #ifdef __i386__ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 0); @@ -459,6 +466,7 @@ static int sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void) filter; #ifdef __i386__ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), 0); @@ -521,6 +529,7 @@ static int sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void) filter; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl), 1, SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_ADD)); @@ -551,6 +560,7 @@ static int sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void) filter; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 1, SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE)); @@ -571,6 +581,7 @@ static int sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void) filter; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 1, SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ)); @@ -598,6 +609,7 @@ static int sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void) filter; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 1, SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK)); @@ -622,6 +634,7 @@ static int sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void) filter; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock), 1, SCMP_CMP(1, SCMP_CMP_EQ, LOCK_EX|LOCK_NB)); @@ -644,6 +657,7 @@ static int sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void) filter; // can remove rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex), 1, @@ -675,6 +689,7 @@ static int sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void) filter; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap), 1, SCMP_CMP(3, SCMP_CMP_EQ, MREMAP_MAYMOVE)); @@ -692,6 +707,7 @@ static int sb_poll(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; + (void) filter; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(poll), 2, SCMP_CMP(1, SCMP_CMP_EQ, 1), @@ -825,13 +841,13 @@ prot_strings(sandbox_cfg_t* cfg) char *param_val = (char*)((smp_param_t *)el->param)->value; size_t param_size = strlen(param_val) + 1; - if (pr_mem_left - param_size >= 0) { + if (pr_mem_left >= param_size) { // copy to protected memcpy(pr_mem_next, param_val, param_size); // re-point el parameter to protected { - void *old_val = ((smp_param_t*)el->param)->value; + void *old_val = (void *) ((smp_param_t*)el->param)->value; tor_free(old_val); } ((smp_param_t*)el->param)->value = (intptr_t) pr_mem_next; @@ -900,7 +916,7 @@ sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_stat, 0, (intptr_t) tor_strdup(file)); + elem = new_element(SCMP_stat, 0, (intptr_t)(void*) tor_strdup(file)); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -942,7 +958,7 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(open), 0, (intptr_t) tor_strdup(file)); + elem = new_element(SCMP_SYS(open), 0, (intptr_t)(void *)tor_strdup(file)); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -985,7 +1001,7 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, int fr) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(openat), 1, (intptr_t) tor_strdup(file)); + elem = new_element(SCMP_SYS(openat), 1, (intptr_t)(void *)tor_strdup(file)); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -1024,11 +1040,11 @@ sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...) } int -sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com) +sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(execve), 1, (intptr_t) tor_strdup(com)); + elem = new_element(SCMP_SYS(execve), 1, (intptr_t)(void *)tor_strdup(com)); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -1141,7 +1157,8 @@ sandbox_add_addrinfo(const char* name) static int add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) { - int i, rc = 0; + unsigned i; + int rc = 0; // function pointer for (i = 0; i < ARRAY_LENGTH(filter_func); i++) { @@ -1162,7 +1179,8 @@ add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) static int add_noparam_filter(scmp_filter_ctx ctx) { - int i, rc = 0; + unsigned i; + int rc = 0; // add general filters for (i = 0; i < ARRAY_LENGTH(filter_nopar_gen); i++) { diff --git a/src/common/sandbox.h b/src/common/sandbox.h index e61e0b3338..a1434cea92 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -191,7 +191,7 @@ int sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...); * function that the char* needs to be free-ed, 0 means the pointer does not * need to be free-ed. */ -int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, char *com); +int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com); /** Function used to add a series of execve allowed filenames to a supplied * configuration. From a6ada1a50cbedebf15667b4448f6890140f56001 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Sep 2013 15:16:30 -0400 Subject: [PATCH 68/81] Fix a warning related to SCMP_CMP definition in header. SCMP_CMP(a,b,c) leaves the fourth field of the structure undefined, giving a missing-initializer error. All of our uses are three-argument, so I'm overriding the default. --- src/common/sandbox.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 1fd2119fa2..c6c93489c8 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -61,6 +61,9 @@ static sandbox_cfg_t *filter_dynamic = NULL; /** Holds a list of pre-recorded results from getaddrinfo().*/ static sb_addr_info_t *sb_addr_info = NULL; +#undef SCMP_CMP +#define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0}) + /** Variable used for storing all syscall numbers that will be allowed with the * stage 1 general Tor sandbox. */ From 05f8429a280f80c94fa7c01f6a5c4b654cd02286 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Sep 2013 15:18:54 -0400 Subject: [PATCH 69/81] Split libevent AC_CHECK_FUNCS call into multiple lines --- configure.ac | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 68c8ce47b9..e2b2dd60cc 100644 --- a/configure.ac +++ b/configure.ac @@ -395,7 +395,12 @@ save_CPPFLAGS="$CPPFLAGS" LIBS="-levent $STATIC_LIBEVENT_FLAGS $TOR_LIB_WS32 $LIBS" LDFLAGS="$TOR_LDFLAGS_libevent $LDFLAGS" CPPFLAGS="$TOR_CPPFLAGS_libevent $CPPFLAGS" -AC_CHECK_FUNCS(event_get_version event_get_version_number event_get_method event_set_log_callback evdns_set_outgoing_bind_address event_base_loopexit) +AC_CHECK_FUNCS([event_get_version \ + event_get_version_number \ + event_get_method \ + event_set_log_callback \ + evdns_set_outgoing_bind_address \ + event_base_loopexit]) AC_CHECK_MEMBERS([struct event.min_heap_idx], , , [#include ]) From 4e00625bbe030f5c1ae54fb7c4c07dd061ab8644 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Sep 2013 15:29:19 -0400 Subject: [PATCH 70/81] Build correctly with older libevents --- configure.ac | 1 + src/or/main.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/configure.ac b/configure.ac index e2b2dd60cc..8992c84e03 100644 --- a/configure.ac +++ b/configure.ac @@ -400,6 +400,7 @@ AC_CHECK_FUNCS([event_get_version \ event_get_method \ event_set_log_callback \ evdns_set_outgoing_bind_address \ + evutil_secure_rng_set_urandom_device_file \ event_base_loopexit]) AC_CHECK_MEMBERS([struct event.min_heap_idx], , , [#include diff --git a/src/or/main.c b/src/or/main.c index 18e8bc44ae..01f6b5c755 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2804,8 +2804,10 @@ tor_main(int argc, char *argv[]) } // registering libevent rng +#ifdef HAVE_EVUTIL_SECURE_RNG_SET_URANDOM_DEVICE_FILE evutil_secure_rng_set_urandom_device_file( (char*) sandbox_intern_string("/dev/urandom")); +#endif } switch (get_options()->command) { From e9ec0cb5506b81f7f7c54e06a95dafac4acb38e3 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Sep 2013 15:37:45 -0400 Subject: [PATCH 71/81] Do not try to add non-existent syscalls. --- src/common/sandbox.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index c6c93489c8..a5bc892973 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -1187,10 +1187,12 @@ add_noparam_filter(scmp_filter_ctx ctx) // add general filters for (i = 0; i < ARRAY_LENGTH(filter_nopar_gen); i++) { + if (filter_nopar_gen[i] < 0) + continue; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i], 0); if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add syscall index %d, " - "received libseccomp error %d", i, rc); + log_err(LD_BUG,"(Sandbox) failed to add syscall index %d (NR=%d), " + "received libseccomp error %d", i, filter_nopar_gen[i], rc); return rc; } } From 49f9c4924e54b55c34050a2ce1053f7cd78eeaf5 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Sep 2013 15:59:41 -0400 Subject: [PATCH 72/81] Fix compilation on OSX --- src/common/address.c | 2 +- src/common/sandbox.c | 77 ++++++++++++++++++++++++++++++++++++++++---- src/common/sandbox.h | 34 +++++++++++++++---- 3 files changed, 98 insertions(+), 15 deletions(-) diff --git a/src/common/address.c b/src/common/address.c index f9647b9a90..945e5e79bd 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -235,7 +235,7 @@ tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr) memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; - err = sandbox_getaddrinfo(name, &hints, &res); + err = sandbox_getaddrinfo(name, NULL, &hints, &res); if (!err) { best = NULL; for (res_p = res; res_p; res_p = res_p->ai_next) { diff --git a/src/common/sandbox.c b/src/common/sandbox.c index a5bc892973..0eb27bc510 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -26,10 +26,6 @@ #include "util.h" #include "tor_queue.h" -#if defined(HAVE_SECCOMP_H) && defined(__linux__) -#define USE_LIBSECCOMP -#endif - #define DEBUGGING_CLOSE #if defined(USE_LIBSECCOMP) @@ -1083,11 +1079,15 @@ sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) } int -sandbox_getaddrinfo(const char *name, const struct addrinfo *hints, - struct addrinfo **res) +sandbox_getaddrinfo(const char *name, const char *servname, + const struct addrinfo *hints, + struct addrinfo **res) { sb_addr_info_t *el; + if (servname != NULL) + return -1; + *res = NULL; for (el = sb_addr_info; el; el = el->next) { @@ -1386,21 +1386,24 @@ sandbox_cfg_new(void) } int -sandbox_init(sandbox_cfg_t* cfg) +sandbox_init(sandbox_cfg_t *cfg) { #if defined(USE_LIBSECCOMP) return initialise_libseccomp_sandbox(cfg); #elif defined(_WIN32) + (void)cfg; log_warn(LD_BUG,"Windows sandboxing is not implemented. The feature is " "currently disabled."); return 0; #elif defined(TARGET_OS_MAC) + (void)cfg; log_warn(LD_BUG,"Mac OSX sandboxing is not implemented. The feature is " "currently disabled"); return 0; #else + (void)cfg; log_warn(LD_BUG,"Sandboxing is not implemented for your platform. The " "feature is currently disabled"); return 0; @@ -1417,3 +1420,63 @@ sandbox_set_debugging_fd(int fd) #endif } +#ifndef USE_LIBSECCOMP +int +sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file, + int fr) +{ + (void)cfg; (void)file; (void)fr; + return 0; +} + +int +sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...) +{ + (void)cfg; + return 0; +} + +int +sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file, + int fr) +{ + (void)cfg; (void)file; (void)fr; + return 0; +} + +int +sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...) +{ + (void)cfg; + return 0; +} + +int +sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com) +{ + (void)cfg; (void)com; + return 0; +} + +int +sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) +{ + (void)cfg; + return 0; +} + +int +sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file, + int fr) +{ + (void)cfg; (void)file; (void)fr; + return 0; +} + +int +sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...) +{ + (void)cfg; + return 0; +} +#endif diff --git a/src/common/sandbox.h b/src/common/sandbox.h index a1434cea92..07c34a4fd8 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -12,6 +12,9 @@ #ifndef SANDBOX_H_ #define SANDBOX_H_ +#include "orconfig.h" +#include "torint.h" + #ifndef SYS_SECCOMP /** @@ -22,12 +25,15 @@ #endif -#include "torint.h" +#if defined(HAVE_SECCOMP_H) && defined(__linux__) +#define USE_LIBSECCOMP +#endif + /** * Linux definitions */ -#ifdef __linux__ +#ifdef USE_LIBSECCOMP #ifndef __USE_GNU #define __USE_GNU @@ -80,8 +86,6 @@ struct sandbox_cfg_elem { /** Next element of the configuration*/ struct sandbox_cfg_elem *next; }; -/** Typedef to structure used to manage a sandbox configuration. */ -typedef struct sandbox_cfg_elem sandbox_cfg_t; /** * Structure used for keeping a linked list of getaddrinfo pre-recorded @@ -127,22 +131,38 @@ typedef struct { #endif -#endif // __linux__ +#endif // USE_LIBSECCOMP +/** Typedef to structure used to manage a sandbox configuration. */ +typedef struct sandbox_cfg_elem sandbox_cfg_t; + +#ifdef USE_LIBSECCOMP /** Pre-calls getaddrinfo in order to pre-record result. */ int sandbox_add_addrinfo(const char *addr); +struct addrinfo; /** Replacement for getaddrinfo(), using pre-recorded results. */ -int sandbox_getaddrinfo(const char *name, const struct addrinfo *hints, - struct addrinfo **res); +int sandbox_getaddrinfo(const char *name, const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); +#else +#define sandbox_getaddrinfo(name, servname, hints, res) \ + getaddrinfo((name),(servname), (hints),(res)) +#define sandbox_add_addrinfo(name) \ + ((void)(name)) +#endif /** Use fd to log non-survivable sandbox violations. */ void sandbox_set_debugging_fd(int fd); +#ifdef USE_LIBSECCOMP /** Returns a registered protected string used with the sandbox, given that * it matches the parameter. */ const char* sandbox_intern_string(const char *param); +#else +#define sandbox_intern_string(s) (s) +#endif /** Creates an empty sandbox configuration file.*/ sandbox_cfg_t * sandbox_cfg_new(void); From d91c776f6133bc8af899889b3ba5af682608fd31 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Sep 2013 16:00:40 -0400 Subject: [PATCH 73/81] Fix check-spaces --- src/common/sandbox.c | 1 + src/common/sandbox.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 0eb27bc510..6db682d518 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -1480,3 +1480,4 @@ sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...) return 0; } #endif + diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 07c34a4fd8..279085fc19 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -29,7 +29,6 @@ #define USE_LIBSECCOMP #endif - /** * Linux definitions */ From 3802cae9597fa417ceec428215159a65195e0f7a Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 10 Sep 2013 00:04:43 +0300 Subject: [PATCH 74/81] fixed compilation error on i386 linux by moving sandbox_cfg_t definition --- src/common/sandbox.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 279085fc19..5df9b111db 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -85,6 +85,8 @@ struct sandbox_cfg_elem { /** Next element of the configuration*/ struct sandbox_cfg_elem *next; }; +/** Typedef to structure used to manage a sandbox configuration. */ +typedef struct sandbox_cfg_elem sandbox_cfg_t; /** * Structure used for keeping a linked list of getaddrinfo pre-recorded @@ -132,9 +134,6 @@ typedef struct { #endif // USE_LIBSECCOMP -/** Typedef to structure used to manage a sandbox configuration. */ -typedef struct sandbox_cfg_elem sandbox_cfg_t; - #ifdef USE_LIBSECCOMP /** Pre-calls getaddrinfo in order to pre-record result. */ int sandbox_add_addrinfo(const char *addr); From 8e003b1c69152ba6e5c3a09db11472eef5db14da Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 10 Sep 2013 00:42:36 +0300 Subject: [PATCH 75/81] fixed socket syscall bug --- src/common/sandbox.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 6db682d518..a852cb697b 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -1187,8 +1187,6 @@ add_noparam_filter(scmp_filter_ctx ctx) // add general filters for (i = 0; i < ARRAY_LENGTH(filter_nopar_gen); i++) { - if (filter_nopar_gen[i] < 0) - continue; rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i], 0); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add syscall index %d (NR=%d), " From 79f94e236b60dca6feebd2350d2c00f0c9a2eeb7 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Tue, 10 Sep 2013 14:35:11 +0300 Subject: [PATCH 76/81] added filter protection for string parameter memory --- src/common/sandbox.c | 58 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index a852cb697b..6d1e6ef1c0 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -587,11 +587,6 @@ sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (rc) return rc; - rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 1, - SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); - if (rc) - return rc; - rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 1, SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE)); if (rc) @@ -810,7 +805,7 @@ sandbox_intern_string(const char *str) * mprotect(). */ static int -prot_strings(sandbox_cfg_t* cfg) +prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) { int ret = 0; size_t pr_mem_size = 0, pr_mem_left = 0; @@ -870,6 +865,48 @@ prot_strings(sandbox_cfg_t* cfg) goto out; } + /* + * Setting sandbox restrictions so the string memory cannot be tampered with + */ + // no mremap of the protected base address + ret = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(mremap), 1, + SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base)); + if (ret) { + log_err(LD_BUG,"(Sandbox) mremap protected memory filter fail!"); + return ret; + } + + // no munmap of the protected base address + ret = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(munmap), 1, + SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base)); + if (ret) { + log_err(LD_BUG,"(Sandbox) munmap protected memory filter fail!"); + return ret; + } + + /* + * Allow mprotect with PROT_READ|PROT_WRITE because openssl uses it, but + * never over the memory region used by the protected strings. + * + * PROT_READ|PROT_WRITE was originally fully allowed in sb_mprotect(), but + * had to be removed due to limitation of libseccomp regarding intervals. + */ + ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 2, + SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base), + SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); + if (ret) { + log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (LT)!"); + return ret; + } + + ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 2, + SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size), + SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); + if (ret) { + log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (GT)!"); + return ret; + } + out: return ret; } @@ -1216,6 +1253,11 @@ install_syscall_filter(sandbox_cfg_t* cfg) goto end; } + // protectign sandbox parameter strings + if ((rc = prot_strings(ctx, cfg))) { + goto end; + } + // add parameter filters if ((rc = add_param_filter(ctx, cfg))) { log_err(LD_BUG, "(Sandbox) failed to add param filters!"); @@ -1362,10 +1404,6 @@ initialise_libseccomp_sandbox(sandbox_cfg_t* cfg) if (install_sigsys_debugging()) return -1; - if (prot_strings(cfg)) { - return -4; - } - if (install_syscall_filter(cfg)) return -2; From 6a11b6f97dabdcf7df7c0d5a7b8577f3cb636154 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 11 Sep 2013 13:53:26 -0400 Subject: [PATCH 77/81] Fix osx compilation again, hopefully better this time. --- src/common/sandbox.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/common/sandbox.h b/src/common/sandbox.h index 5df9b111db..1d39be4090 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -29,6 +29,11 @@ #define USE_LIBSECCOMP #endif +struct sandbox_cfg_elem; + +/** Typedef to structure used to manage a sandbox configuration. */ +typedef struct sandbox_cfg_elem sandbox_cfg_t; + /** * Linux definitions */ @@ -85,8 +90,6 @@ struct sandbox_cfg_elem { /** Next element of the configuration*/ struct sandbox_cfg_elem *next; }; -/** Typedef to structure used to manage a sandbox configuration. */ -typedef struct sandbox_cfg_elem sandbox_cfg_t; /** * Structure used for keeping a linked list of getaddrinfo pre-recorded From 4702cdc99d734ebb7bbb68d65c00a91fdbc13463 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 12 Sep 2013 13:43:06 +0300 Subject: [PATCH 78/81] added extra buffer and limit to mprotect not to exceed the length of that buffer --- src/common/sandbox.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 6d1e6ef1c0..5961c06414 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -15,6 +15,9 @@ */ #define _LARGEFILE64_SOURCE +/** Malloc mprotect limit in bytes. */ +#define MALLOC_MP_LIM 1048576 + #include #include #include @@ -50,6 +53,10 @@ #include #include +// TODO: remove test +static void *test_buf_base = NULL; +static int test_buf_len = 0; + /**Determines if at least one sandbox is active.*/ static int sandbox_active = 0; /** Holds the parameter list configuration for the sandbox.*/ @@ -817,9 +824,9 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) pr_mem_size += strlen((char*) ((smp_param_t*)el->param)->value) + 1; } - // allocate protected memory - pr_mem_base = (char*) mmap(NULL, pr_mem_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, -1, 0); + // allocate protected memory with MALLOC_MP_LIM canary + pr_mem_base = (char*) mmap(NULL, MALLOC_MP_LIM + pr_mem_size, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (pr_mem_base == MAP_FAILED) { log_err(LD_BUG,"(Sandbox) failed allocate protected memory! mmap: %s", strerror(errno)); @@ -827,7 +834,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) goto out; } - pr_mem_next = pr_mem_base; + pr_mem_next = pr_mem_base + MALLOC_MP_LIM; pr_mem_left = pr_mem_size; // change el value pointer to protected @@ -857,8 +864,12 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) } } + // TODO: remove, test + test_buf_base = pr_mem_base; + test_buf_len = pr_mem_size; + // protecting from writes - if (mprotect(pr_mem_base, pr_mem_size, PROT_READ)) { + if (mprotect(pr_mem_base, MALLOC_MP_LIM + pr_mem_size, PROT_READ)) { log_err(LD_BUG,"(Sandbox) failed to protect memory! mprotect: %s", strerror(errno)); ret = -3; @@ -890,9 +901,13 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) * * PROT_READ|PROT_WRITE was originally fully allowed in sb_mprotect(), but * had to be removed due to limitation of libseccomp regarding intervals. + * + * There is a restriction on how much you can mprotect with R|W up to the + * size of the canary. */ ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 2, SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base), + SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM), SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); if (ret) { log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (LT)!"); @@ -900,8 +915,10 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) } ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 2, - SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size), - SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); + SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size + + MALLOC_MP_LIM), + SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM), + SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); if (ret) { log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (GT)!"); return ret; From 0a3d1685ae7f7dd62b829466e8abae75a17a2482 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 12 Sep 2013 14:12:56 +0300 Subject: [PATCH 79/81] remove debugging code --- src/common/sandbox.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 5961c06414..dc8885e185 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -53,10 +53,6 @@ #include #include -// TODO: remove test -static void *test_buf_base = NULL; -static int test_buf_len = 0; - /**Determines if at least one sandbox is active.*/ static int sandbox_active = 0; /** Holds the parameter list configuration for the sandbox.*/ @@ -864,10 +860,6 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) } } - // TODO: remove, test - test_buf_base = pr_mem_base; - test_buf_len = pr_mem_size; - // protecting from writes if (mprotect(pr_mem_base, MALLOC_MP_LIM + pr_mem_size, PROT_READ)) { log_err(LD_BUG,"(Sandbox) failed to protect memory! mprotect: %s", From d2836c8780373eff011ba42620d5ab48f342cf78 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 12 Sep 2013 15:30:28 +0300 Subject: [PATCH 80/81] bug fix: syscalls send and recv not supported for x86_64 with libseccomp 1.0.1 --- src/common/sandbox.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index dc8885e185..db2ad1d6ff 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -129,12 +129,19 @@ static int filter_nopar_gen[] = { SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname), - SCMP_SYS(recv), SCMP_SYS(recvmsg), SCMP_SYS(recvfrom), SCMP_SYS(sendto), - SCMP_SYS(send), SCMP_SYS(unlink) + + /* + * These syscalls are not required on x86_64 and not supported with + * some libseccomp versions (eg: 1.0.1) + */ +#if defined(__i386) + SCMP_SYS(recv), + SCMP_SYS(send), +#endif }; /** From 7cf1b9cc33ab2ba13d84e08105699dd1f39dae1d Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Thu, 12 Sep 2013 15:38:14 +0300 Subject: [PATCH 81/81] fixed compilation bug on i386 due to previous fix --- src/common/sandbox.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/common/sandbox.c b/src/common/sandbox.c index db2ad1d6ff..b9ec99efa3 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -125,6 +125,15 @@ static int filter_nopar_gen[] = { SCMP_SYS(stat64), #endif + /* + * These socket syscalls are not required on x86_64 and not supported with + * some libseccomp versions (eg: 1.0.1) + */ +#if defined(__i386) + SCMP_SYS(recv), + SCMP_SYS(send), +#endif + // socket syscalls SCMP_SYS(bind), SCMP_SYS(connect), @@ -133,15 +142,6 @@ static int filter_nopar_gen[] = { SCMP_SYS(recvfrom), SCMP_SYS(sendto), SCMP_SYS(unlink) - - /* - * These syscalls are not required on x86_64 and not supported with - * some libseccomp versions (eg: 1.0.1) - */ -#if defined(__i386) - SCMP_SYS(recv), - SCMP_SYS(send), -#endif }; /**