From 8a85a48b9d0ed2b298bcc26dfeb96fa7e31c05c4 Mon Sep 17 00:00:00 2001 From: Cristian Toader Date: Mon, 12 Aug 2013 21:14:43 +0300 Subject: [PATCH] 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");