diff --git a/src/common/sandbox.c b/src/common/sandbox.c index 68be89e8816e895caaa1aac28fc016efefdeef4f..56feae008de25cc6c8171463e6763e9bfa0bb83f 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -25,11 +25,18 @@ #if defined(USE_LIBSECCOMP) +#include <sys/mman.h> #include <sys/syscall.h> #include <seccomp.h> #include <signal.h> #include <unistd.h> +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,6 +149,81 @@ static int general_filter[] = { SCMP_SYS(unlink) }; +static int +add_param_filter(scmp_filter_ctx ctx) +{ + int i, filter_size, param_size, rc = 0; + void *map = NULL; + + 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 { + 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); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add syscall index %d, " + "received libseccomp error %d", i, rc); + 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. @@ -150,7 +232,7 @@ static int general_filter[] = { static int install_glob_syscall_filter(void) { - int rc = 0, i, filter_size; + int rc = 0; scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_TRAP); @@ -160,20 +242,16 @@ install_glob_syscall_filter(void) goto end; } - if (general_filter != NULL) { - filter_size = sizeof(general_filter) / sizeof(general_filter[0]); - } else { - filter_size = 0; + // add parameter filters + if ((rc = add_param_filter(ctx))) { + log_err(LD_BUG, "(Sandbox) failed to add param filters!"); + goto end; } - // add general filters - for (i = 0; i < filter_size; i++) { - rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, general_filter[i], 0); - if (rc != 0) { - log_err(LD_BUG,"(Sandbox) failed to add syscall index %d, " - "received libseccomp error %d", i, rc); - 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); diff --git a/src/common/sandbox.h b/src/common/sandbox.h index bd6f0cfb4738fe2997656f6d201e22a7384a528f..cfbecebbd476bdb58a4b1c2562649546a0f83a3e 100644 --- a/src/common/sandbox.h +++ b/src/common/sandbox.h @@ -30,6 +30,14 @@ #define __USE_GNU #include <sys/ucontext.h> +#define MAX_PARAM_LEN 32 + +typedef struct { + int syscall; + char *param; + char prot; +} ParFilter; + /** * Linux 32 bit definitions */