diff options
Diffstat (limited to 'src/common/sandbox.c')
-rw-r--r-- | src/common/sandbox.c | 476 |
1 files changed, 324 insertions, 152 deletions
diff --git a/src/common/sandbox.c b/src/common/sandbox.c index e43b64b913..b90ae02578 100644 --- a/src/common/sandbox.c +++ b/src/common/sandbox.c @@ -1,7 +1,7 @@ -/* Copyright (c) 2001 Matej Pfajfar. + /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2013, The Tor Project, Inc. */ + * Copyright (c) 2007-2016, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -39,8 +39,6 @@ #if defined(USE_LIBSECCOMP) -#define _GNU_SOURCE - #include <sys/mman.h> #include <sys/syscall.h> #include <sys/types.h> @@ -48,7 +46,7 @@ #include <sys/epoll.h> #include <sys/prctl.h> #include <linux/futex.h> -#include <bits/signum.h> +#include <sys/file.h> #include <stdarg.h> #include <seccomp.h> @@ -58,6 +56,19 @@ #include <time.h> #include <poll.h> +#ifdef HAVE_GNU_LIBC_VERSION_H +#include <gnu/libc-version.h> +#endif +#ifdef HAVE_LINUX_NETFILTER_IPV4_H +#include <linux/netfilter_ipv4.h> +#endif +#ifdef HAVE_LINUX_IF_H +#include <linux/if.h> +#endif +#ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H +#include <linux/netfilter_ipv6/ip6_tables.h> +#endif + #if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \ defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION) #define USE_BACKTRACE @@ -98,6 +109,8 @@ static sandbox_cfg_t *filter_dynamic = NULL; #undef SCMP_CMP #define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0}) +#define SCMP_CMP_STR(a,b,c) \ + ((struct scmp_arg_cmp) {(a),(b),(intptr_t)(void*)(c),0}) #define SCMP_CMP4(a,b,c,d) ((struct scmp_arg_cmp){(a),(b),(c),(d)}) /* We use a wrapper here because these masked comparisons seem to be pretty * verbose. Also, it's important to cast to scmp_datum_t before negating the @@ -117,11 +130,27 @@ static int filter_nopar_gen[] = { SCMP_SYS(clone), SCMP_SYS(epoll_create), SCMP_SYS(epoll_wait), +#ifdef __NR_epoll_pwait + SCMP_SYS(epoll_pwait), +#endif +#ifdef HAVE_EVENTFD + SCMP_SYS(eventfd2), +#endif +#ifdef HAVE_PIPE2 + SCMP_SYS(pipe2), +#endif +#ifdef HAVE_PIPE + SCMP_SYS(pipe), +#endif +#ifdef __NR_fchmod + SCMP_SYS(fchmod), +#endif SCMP_SYS(fcntl), SCMP_SYS(fstat), #ifdef __NR_fstat64 SCMP_SYS(fstat64), #endif + SCMP_SYS(futex), SCMP_SYS(getdents64), SCMP_SYS(getegid), #ifdef __NR_getegid32 @@ -135,6 +164,7 @@ static int filter_nopar_gen[] = { #ifdef __NR_getgid32 SCMP_SYS(getgid32), #endif + SCMP_SYS(getpid), #ifdef __NR_getrlimit SCMP_SYS(getrlimit), #endif @@ -155,10 +185,26 @@ static int filter_nopar_gen[] = { SCMP_SYS(mmap), #endif SCMP_SYS(munmap), +#ifdef __NR_prlimit + SCMP_SYS(prlimit), +#endif +#ifdef __NR_prlimit64 + SCMP_SYS(prlimit64), +#endif SCMP_SYS(read), SCMP_SYS(rt_sigreturn), SCMP_SYS(sched_getaffinity), +#ifdef __NR_sched_yield + SCMP_SYS(sched_yield), +#endif + SCMP_SYS(sendmsg), SCMP_SYS(set_robust_list), +#ifdef __NR_setrlimit + SCMP_SYS(setrlimit), +#endif +#ifdef __NR_sigaltstack + SCMP_SYS(sigaltstack), +#endif #ifdef __NR_sigreturn SCMP_SYS(sigreturn), #endif @@ -176,6 +222,14 @@ static int filter_nopar_gen[] = { SCMP_SYS(stat64), #endif +#ifdef __NR_getrandom + SCMP_SYS(getrandom), +#endif + +#ifdef __NR_sysinfo + // qsort uses this.. + SCMP_SYS(sysinfo), +#endif /* * These socket syscalls are not required on x86_64 and not supported with * some libseccomp versions (eg: 1.0.1) @@ -253,7 +307,7 @@ sb_execve(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(execve)) { rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(execve), - SCMP_CMP(0, SCMP_CMP_EQ, param->value)); + SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add execve syscall, received " "libseccomp error %d", rc); @@ -373,6 +427,52 @@ sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } #endif +#ifdef HAVE_GNU_LIBC_VERSION_H +#ifdef HAVE_GNU_GET_LIBC_VERSION +#define CHECK_LIBC_VERSION +#endif +#endif + +/* Return true if we think we're running with a libc that always uses + * openat on linux. */ +static int +libc_uses_openat_for_everything(void) +{ +#ifdef CHECK_LIBC_VERSION + const char *version = gnu_get_libc_version(); + if (version == NULL) + return 0; + + int major = -1; + int minor = -1; + + tor_sscanf(version, "%d.%d", &major, &minor); + if (major >= 3) + return 1; + else if (major == 2 && minor >= 26) + return 1; + else + return 0; +#else + return 0; +#endif +} + +/** Allow a single file to be opened. If <b>use_openat</b> is true, + * we're using a libc that remaps all the opens into openats. */ +static int +allow_file_open(scmp_filter_ctx ctx, int use_openat, const char *file) +{ + if (use_openat) { + return seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), + SCMP_CMP_STR(0, SCMP_CMP_EQ, AT_FDCWD), + SCMP_CMP_STR(1, SCMP_CMP_EQ, file)); + } else { + return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), + SCMP_CMP_STR(0, SCMP_CMP_EQ, file)); + } +} + /** * Function responsible for setting up the open syscall for * the seccomp filter sandbox. @@ -383,14 +483,15 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) int rc; sandbox_cfg_t *elem = NULL; + int use_openat = libc_uses_openat_for_everything(); + // for each dynamic parameter filters for (elem = filter; elem != NULL; elem = elem->next) { smp_param_t *param = elem->param; if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(open)) { - rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), - SCMP_CMP(0, SCMP_CMP_EQ, param->value)); + rc = allow_file_open(ctx, use_openat, param->value); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " "libseccomp error %d", rc); @@ -400,13 +501,73 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } rc = seccomp_rule_add_1(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(open), - SCMP_CMP_MASKED(1, O_CLOEXEC|O_NONBLOCK|O_NOCTTY, O_RDONLY)); + SCMP_CMP_MASKED(1, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|O_NOFOLLOW, + O_RDONLY)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add open syscall, received libseccomp " "error %d", rc); return rc; } + rc = seccomp_rule_add_1(ctx, SCMP_ACT_ERRNO(EACCES), SCMP_SYS(openat), + SCMP_CMP_MASKED(2, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|O_NOFOLLOW, + O_RDONLY)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received " + "libseccomp error %d", rc); + return rc; + } + + return 0; +} + +static int +sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +{ + int rc; + sandbox_cfg_t *elem = NULL; + + // for each dynamic parameter filters + for (elem = filter; elem != NULL; elem = elem->next) { + smp_param_t *param = elem->param; + + if (param != NULL && param->prot == 1 && param->syscall + == SCMP_SYS(chmod)) { + rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chmod), + SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " + "libseccomp error %d", rc); + return rc; + } + } + } + + return 0; +} + +static int +sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +{ + int rc; + sandbox_cfg_t *elem = NULL; + + // for each dynamic parameter filters + for (elem = filter; elem != NULL; elem = elem->next) { + smp_param_t *param = elem->param; + + if (param != NULL && param->prot == 1 && param->syscall + == SCMP_SYS(chown)) { + rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown), + SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " + "libseccomp error %d", rc); + return rc; + } + } + } + return 0; } @@ -445,8 +606,8 @@ sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter) param->syscall == SCMP_SYS(rename)) { rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename), - SCMP_CMP(0, SCMP_CMP_EQ, param->value), - SCMP_CMP(1, SCMP_CMP_EQ, param->value2)); + SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value), + SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received " "libseccomp error %d", rc); @@ -476,7 +637,7 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) == SCMP_SYS(openat)) { rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), SCMP_CMP(0, SCMP_CMP_EQ, AT_FDCWD), - SCMP_CMP(1, SCMP_CMP_EQ, param->value), + SCMP_CMP_STR(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) { @@ -498,7 +659,7 @@ static int sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) { int rc = 0; - int i; + int i, j; (void) filter; #ifdef __i386__ @@ -515,25 +676,38 @@ sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter) for (i = 0; i < 2; ++i) { const int pf = i ? PF_INET : PF_INET6; + for (j=0; j < 3; ++j) { + const int type = (j == 0) ? SOCK_STREAM : + SOCK_DGRAM; + const int protocol = (j == 0) ? IPPROTO_TCP : + (j == 1) ? IPPROTO_IP : + IPPROTO_UDP; + rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), + SCMP_CMP(0, SCMP_CMP_EQ, pf), + SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, type), + SCMP_CMP(2, SCMP_CMP_EQ, protocol)); + if (rc) + return rc; + } + } - rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), - SCMP_CMP(0, SCMP_CMP_EQ, pf), + rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), + SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX), SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM), - SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_TCP)); - if (rc) - return rc; + SCMP_CMP(2, SCMP_CMP_EQ, 0)); + if (rc) + return rc; - rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), - SCMP_CMP(0, SCMP_CMP_EQ, pf), + rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), + SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX), SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM), - SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP)); - if (rc) - return rc; - } + SCMP_CMP(2, SCMP_CMP_EQ, 0)); + if (rc) + return rc; rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK), - SCMP_CMP(1, SCMP_CMP_EQ, SOCK_RAW), + SCMP_CMP_MASKED(1, SOCK_CLOEXEC, SOCK_RAW), SCMP_CMP(2, SCMP_CMP_EQ, 0)); if (rc) return rc; @@ -600,6 +774,14 @@ sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (rc) return rc; +#ifdef HAVE_SYSTEMD + rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), + SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET), + SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUFFORCE)); + if (rc) + return rc; +#endif + #ifdef IP_TRANSPARENT rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP), @@ -608,6 +790,14 @@ sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return rc; #endif +#ifdef IPV6_V6ONLY + rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), + SCMP_CMP(1, SCMP_CMP_EQ, IPPROTO_IPV6), + SCMP_CMP(2, SCMP_CMP_EQ, IPV6_V6ONLY)); + if (rc) + return rc; +#endif + return 0; } @@ -633,6 +823,30 @@ sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (rc) return rc; +#ifdef HAVE_SYSTEMD + rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), + SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET), + SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF)); + if (rc) + return rc; +#endif + +#ifdef HAVE_LINUX_NETFILTER_IPV4_H + rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), + SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP), + SCMP_CMP(2, SCMP_CMP_EQ, SO_ORIGINAL_DST)); + if (rc) + return rc; +#endif + +#ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H + rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt), + SCMP_CMP(1, SCMP_CMP_EQ, SOL_IPV6), + SCMP_CMP(2, SCMP_CMP_EQ, IP6T_SO_ORIGINAL_DST)); + if (rc) + return rc; +#endif + return 0; } @@ -704,7 +918,7 @@ sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } /** - * Function responsible for setting up the fcntl64 syscall for + * Function responsible for setting up the prctl syscall for * the seccomp filter sandbox. * * NOTE: if multiple filters need to be added, the PR_SECCOMP parameter needs @@ -725,7 +939,7 @@ sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } /** - * Function responsible for setting up the fcntl64 syscall for + * Function responsible for setting up the mprotect syscall for * the seccomp filter sandbox. * * NOTE: does not NEED to be here.. currently only occurs before filter; will @@ -885,7 +1099,7 @@ sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open) || param->syscall == SCMP_SYS(stat64))) { rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64), - SCMP_CMP(0, SCMP_CMP_EQ, param->value)); + SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value)); if (rc != 0) { log_err(LD_BUG,"(Sandbox) failed to add open syscall, received " "libseccomp error %d", rc); @@ -898,6 +1112,19 @@ sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } #endif +static int +sb_kill(scmp_filter_ctx ctx, sandbox_cfg_t *filter) +{ + (void) filter; +#ifdef __NR_kill + /* Allow killing anything with signal 0 -- it isn't really a kill. */ + return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(kill), + SCMP_CMP(1, SCMP_CMP_EQ, 0)); +#else + return 0; +#endif +} + /** * Array of function pointers responsible for filtering different syscalls at * a parameter level. @@ -913,6 +1140,8 @@ static sandbox_filter_func_t filter_func[] = { #ifdef __NR_mmap2 sb_mmap2, #endif + sb_chown, + sb_chmod, sb_open, sb_openat, sb__sysctl, @@ -934,7 +1163,8 @@ static sandbox_filter_func_t filter_func[] = { sb_socket, sb_setsockopt, sb_getsockopt, - sb_socketpair + sb_socketpair, + sb_kill }; const char * @@ -963,12 +1193,12 @@ sandbox_intern_string(const char *str) return str; } -/** DOCDOC */ +/* DOCDOC */ static int prot_strings_helper(strmap_t *locations, char **pr_mem_next_p, size_t *pr_mem_left_p, - intptr_t *value_p) + char **value_p) { char *param_val; size_t param_size; @@ -984,7 +1214,7 @@ prot_strings_helper(strmap_t *locations, if (location) { // We already interned this string. tor_free(param_val); - *value_p = (intptr_t) location; + *value_p = location; return 0; } else if (*pr_mem_left_p >= param_size) { // copy to protected @@ -993,7 +1223,7 @@ prot_strings_helper(strmap_t *locations, // re-point el parameter to protected tor_free(param_val); - *value_p = (intptr_t) location; + *value_p = location; strmap_set(locations, location, location); /* good real estate advice */ @@ -1075,7 +1305,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) 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; + goto out; } // no munmap of the protected base address @@ -1083,7 +1313,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) 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; + goto out; } /* @@ -1102,7 +1332,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) 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; + goto out; } ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), @@ -1112,7 +1342,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) 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; + goto out; } out: @@ -1122,12 +1352,12 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) /** * 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 + * its values according 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_element2(int syscall, intptr_t value, intptr_t value2) +new_element2(int syscall, char *value, char *value2) { smp_param_t *param = NULL; @@ -1143,9 +1373,9 @@ new_element2(int syscall, intptr_t value, intptr_t value2) } static sandbox_cfg_t* -new_element(int syscall, intptr_t value) +new_element(int syscall, char *value) { - return new_element2(syscall, value, 0); + return new_element2(syscall, value, NULL); } #ifdef __NR_stat64 @@ -1159,7 +1389,7 @@ sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_stat, (intptr_t)(void*) file); + elem = new_element(SCMP_stat, file); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -1172,33 +1402,28 @@ sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file) } int -sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...) +sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) { - int rc = 0; - char *fn = NULL; - - va_list ap; - va_start(ap, cfg); + sandbox_cfg_t *elem = NULL; - while ((fn = va_arg(ap, char*)) != NULL) { - rc = sandbox_cfg_allow_stat_filename(cfg, fn); - if (rc) { - log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_stat_filename_array fail"); - goto end; - } + elem = new_element(SCMP_SYS(open), file); + if (!elem) { + log_err(LD_BUG,"(Sandbox) failed to register parameter!"); + return -1; } - end: - va_end(ap); + elem->next = *cfg; + *cfg = elem; + return 0; } int -sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) +sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(open), (intptr_t)(void *) file); + elem = new_element(SCMP_SYS(chmod), file); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -1211,14 +1436,11 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) } int -sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2) +sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file) { sandbox_cfg_t *elem = NULL; - elem = new_element2(SCMP_SYS(rename), - (intptr_t)(void *) file1, - (intptr_t)(void *) file2); - + elem = new_element(SCMP_SYS(chown), file); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -1231,24 +1453,20 @@ sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2) } int -sandbox_cfg_allow_open_filename_array(sandbox_cfg_t **cfg, ...) +sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2) { - int rc = 0; - char *fn = NULL; + sandbox_cfg_t *elem = NULL; - va_list ap; - va_start(ap, cfg); + elem = new_element2(SCMP_SYS(rename), file1, file2); - while ((fn = va_arg(ap, char*)) != NULL) { - rc = sandbox_cfg_allow_open_filename(cfg, fn); - if (rc) { - log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_open_filename_array fail"); - goto end; - } + if (!elem) { + log_err(LD_BUG,"(Sandbox) failed to register parameter!"); + return -1; } - end: - va_end(ap); + elem->next = *cfg; + *cfg = elem; + return 0; } @@ -1257,7 +1475,7 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(openat), (intptr_t)(void *) file); + elem = new_element(SCMP_SYS(openat), file); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -1269,35 +1487,13 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file) return 0; } -int -sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...) -{ - int rc = 0; - char *fn = NULL; - - va_list ap; - va_start(ap, cfg); - - while ((fn = va_arg(ap, char*)) != NULL) { - rc = sandbox_cfg_allow_openat_filename(cfg, fn); - if (rc) { - log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_openat_filename_array fail"); - goto end; - } - } - - end: - va_end(ap); - return 0; -} - #if 0 int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(execve), (intptr_t)(void *) com); + elem = new_element(SCMP_SYS(execve), com); if (!elem) { log_err(LD_BUG,"(Sandbox) failed to register parameter!"); return -1; @@ -1309,28 +1505,6 @@ sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com) return 0; } -int -sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) -{ - int rc = 0; - char *fn = NULL; - - va_list ap; - va_start(ap, cfg); - - while ((fn = va_arg(ap, char*)) != NULL) { - - rc = sandbox_cfg_allow_execve(cfg, fn); - if (rc) { - log_err(LD_BUG,"(Sandbox) sandbox_cfg_allow_execve_array failed"); - goto end; - } - } - - end: - va_end(ap); - return 0; -} #endif /** Cache entry for getaddrinfo results; used when sandboxing is implemented @@ -1380,11 +1554,11 @@ static HT_HEAD(getaddrinfo_cache, cached_getaddrinfo_item_t) HT_PROTOTYPE(getaddrinfo_cache, cached_getaddrinfo_item_t, node, cached_getaddrinfo_item_hash, - cached_getaddrinfo_items_eq); -HT_GENERATE(getaddrinfo_cache, cached_getaddrinfo_item_t, node, - cached_getaddrinfo_item_hash, - cached_getaddrinfo_items_eq, - 0.6, tor_malloc_, tor_realloc_, tor_free_); + cached_getaddrinfo_items_eq) +HT_GENERATE2(getaddrinfo_cache, cached_getaddrinfo_item_t, node, + cached_getaddrinfo_item_hash, + cached_getaddrinfo_items_eq, + 0.6, tor_reallocarray_, tor_free_) /** If true, don't try to cache getaddrinfo results. */ static int sandbox_getaddrinfo_cache_disabled = 0; @@ -1398,6 +1572,13 @@ sandbox_disable_getaddrinfo_cache(void) sandbox_getaddrinfo_cache_disabled = 1; } +void +sandbox_freeaddrinfo(struct addrinfo *ai) +{ + if (sandbox_getaddrinfo_cache_disabled) + freeaddrinfo(ai); +} + int sandbox_getaddrinfo(const char *name, const char *servname, const struct addrinfo *hints, @@ -1486,13 +1667,14 @@ sandbox_add_addrinfo(const char *name) void sandbox_free_getaddrinfo_cache(void) { - cached_getaddrinfo_item_t **next, **item; + cached_getaddrinfo_item_t **next, **item, *this; for (item = HT_START(getaddrinfo_cache, &getaddrinfo_cache); item; item = next) { + this = *item; next = HT_NEXT_RMV(getaddrinfo_cache, &getaddrinfo_cache, item); - cached_getaddrinfo_item_free(*item); + cached_getaddrinfo_item_free(this); } HT_CLEAR(getaddrinfo_cache, &getaddrinfo_cache); @@ -1510,7 +1692,8 @@ 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, cfg)) { + rc = filter_func[i](ctx, cfg); + if (rc) { log_err(LD_BUG,"(Sandbox) failed to add syscall %d, received libseccomp " "error %d", i, rc); return rc; @@ -1628,7 +1811,7 @@ sigsys_debugging(int nr, siginfo_t *info, void *void_context) const char *syscall_name; int syscall; #ifdef USE_BACKTRACE - int depth; + size_t depth; int n_fds, i; const int *fds = NULL; #endif @@ -1660,7 +1843,7 @@ sigsys_debugging(int nr, siginfo_t *info, void *void_context) #ifdef USE_BACKTRACE n_fds = tor_log_get_sigsafe_err_fds(&fds); for (i=0; i < n_fds; ++i) - backtrace_symbols_fd(syscall_cb_buf, depth, fds[i]); + backtrace_symbols_fd(syscall_cb_buf, (int)depth, fds[i]); #endif #if defined(DEBUGGING_CLOSE) @@ -1732,6 +1915,9 @@ register_cfg(sandbox_cfg_t* cfg) static int initialise_libseccomp_sandbox(sandbox_cfg_t* cfg) { + /* Prevent glibc from trying to open /dev/tty on fatal error */ + setenv("LIBC_FATAL_STDERR_", "1", 1); + if (install_sigsys_debugging()) return -1; @@ -1789,26 +1975,12 @@ sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file) } 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) { (void)cfg; (void)file; return 0; } -int -sandbox_cfg_allow_openat_filename_array(sandbox_cfg_t **cfg, ...) -{ - (void)cfg; - return 0; -} - #if 0 int sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com) @@ -1816,26 +1988,26 @@ sandbox_cfg_allow_execve(sandbox_cfg_t **cfg, const char *com) (void)cfg; (void)com; return 0; } +#endif int -sandbox_cfg_allow_execve_array(sandbox_cfg_t **cfg, ...) +sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file) { - (void)cfg; + (void)cfg; (void)file; return 0; } -#endif int -sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file) +sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file) { (void)cfg; (void)file; return 0; } int -sandbox_cfg_allow_stat_filename_array(sandbox_cfg_t **cfg, ...) +sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file) { - (void)cfg; + (void)cfg; (void)file; return 0; } |