Loading src/lib/fs/conffile.c +31 −10 Original line number Diff line number Diff line Loading @@ -19,9 +19,11 @@ #include "lib/fs/path.h" #include "lib/log/log.h" #include "lib/malloc/malloc.h" #include "lib/sandbox/sandbox.h" #include "lib/string/printf.h" #include <stdbool.h> #include <errno.h> static smartlist_t *config_get_file_list(const char *path, smartlist_t *opened_files); Loading Loading @@ -52,21 +54,26 @@ config_get_lines_include(const char *string, config_line_t **result, opened_lst, 1, NULL, config_process_include); } /** Returns a list of paths obtained when expading globs in <b>pattern</b>. If * <b>pattern</b> has no globs, returns a list with <b>pattern</b> if it is an * existing path or NULL otherwise. If <b>opened_files</b> is provided, adds * paths opened by glob to it. Returns NULL on failure. */ /** Return a list of paths obtained when expading globs in <b>pattern</b>. * If <b>pattern</b> has no globs, return a list with <b>pattern</b> in it. * If <b>opened_files</b> is provided, add paths opened by glob to it. * Return NULL on failure. */ static smartlist_t * expand_glob(const char *pattern, smartlist_t *opened_files) { if (! has_glob(pattern)) { smartlist_t *matches = smartlist_new(); smartlist_add_strdup(matches, pattern); return matches; } smartlist_t *matches = tor_glob(pattern); if (!matches) { return NULL; if (errno == EPERM) { log_err(LD_CONFIG, "Sandbox is active, but the configuration pattern " "\"%s\" listed with %%include would access files or folders not " "allowed by it. Cannot proceed.", pattern); } // if it is not a glob, return error when the path is missing if (!has_glob(pattern) && smartlist_len(matches) == 0) { smartlist_free(matches); return NULL; } Loading Loading @@ -107,6 +114,13 @@ config_get_file_list(const char *pattern, smartlist_t *opened_files) if (opened_files) { smartlist_add_strdup(opened_files, path); } if (sandbox_interned_string_is_missing(path)) { log_err(LD_CONFIG, "Sandbox is active, but a new configuration " "file \"%s\" has been listed with %%include. Cannot proceed.", path); error_found = true; break; } file_status_t file_type = file_status(path); if (file_type == FN_FILE) { Loading Loading @@ -201,6 +215,13 @@ config_process_include(const char *pattern, int recursion_level, int extended, int rv = -1; SMARTLIST_FOREACH_BEGIN(config_files, const char *, config_file) { if (sandbox_interned_string_is_missing(config_file)) { log_err(LD_CONFIG, "Sandbox is active, but a new configuration " "file \"%s\" has been listed with %%include. Cannot proceed.", config_file); goto done; } log_notice(LD_CONFIG, "Including configuration file \"%s\".", config_file); config_line_t *included_config = NULL; config_line_t *included_config_last = NULL; Loading src/lib/fs/path.c +14 −1 Original line number Diff line number Diff line Loading @@ -537,6 +537,10 @@ unglob_win32(const char *pattern, int prev_sep, int next_sep) static DIR * prot_opendir(const char *name) { if (sandbox_interned_string_is_missing(name)) { errno = EPERM; return NULL; } return opendir(sandbox_intern_string(name)); } Loading @@ -544,6 +548,10 @@ prot_opendir(const char *name) static int prot_stat(const char *pathname, struct stat *buf) { if (sandbox_interned_string_is_missing(pathname)) { errno = EPERM; return -1; } return stat(sandbox_intern_string(pathname), buf); } Loading @@ -551,6 +559,10 @@ prot_stat(const char *pathname, struct stat *buf) static int prot_lstat(const char *pathname, struct stat *buf) { if (sandbox_interned_string_is_missing(pathname)) { errno = EPERM; return -1; } return lstat(sandbox_intern_string(pathname), buf); } /** As closedir, but has the right type for gl_closedir */ Loading @@ -563,7 +575,8 @@ wrap_closedir(void *arg) /** Return a new list containing the paths that match the pattern * <b>pattern</b>. Return NULL on error. On POSIX systems, errno is set by the * glob function. * glob function or is set to EPERM if glob tried to access a file not allowed * by the seccomp sandbox. */ struct smartlist_t * tor_glob(const char *pattern) Loading src/lib/sandbox/sandbox.c +36 −3 Original line number Diff line number Diff line Loading @@ -310,6 +310,8 @@ static int filter_nopar_gen[] = { #define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \ seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4)) static const char *sandbox_get_interned_string(const char *str); /** * Function responsible for setting up the rt_sigaction syscall for * the seccomp filter sandbox. Loading Loading @@ -1224,8 +1226,41 @@ static sandbox_filter_func_t filter_func[] = { sb_kill }; /** * Return the interned (and hopefully sandbox-permitted) string equal * to @a str. * * Return NULL if `str` is NULL, or `str` is not an interned string. **/ const char * sandbox_intern_string(const char *str) { const char *interned = sandbox_get_interned_string(str); if (sandbox_active && str != NULL && interned == NULL) { log_warn(LD_BUG, "No interned sandbox parameter found for %s", str); } return interned ? interned : str; } /** * Return true if the sandbox is running and we are missing an interned string * equal to @a str. */ bool sandbox_interned_string_is_missing(const char *str) { return sandbox_active && sandbox_get_interned_string(str) == NULL; } /** * Try to find and return the interned string equal to @a str. * * If there is no such string, return NULL. **/ static const char * sandbox_get_interned_string(const char *str) { sandbox_cfg_t *elem; Loading @@ -1245,9 +1280,7 @@ sandbox_intern_string(const char *str) } } if (sandbox_active) log_warn(LD_BUG, "No interned sandbox parameter found for %s", str); return str; return NULL; } /* DOCDOC */ Loading src/lib/sandbox/sandbox.h +2 −3 Original line number Diff line number Diff line Loading @@ -104,12 +104,11 @@ typedef struct { #endif /* defined(USE_LIBSECCOMP) */ #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); bool sandbox_interned_string_is_missing(const char *s); #else /* !defined(USE_LIBSECCOMP) */ #define sandbox_intern_string(s) (s) #define sandbox_interned_string_is_missing(s) (false) #endif /* defined(USE_LIBSECCOMP) */ /** Creates an empty sandbox configuration file.*/ Loading Loading
src/lib/fs/conffile.c +31 −10 Original line number Diff line number Diff line Loading @@ -19,9 +19,11 @@ #include "lib/fs/path.h" #include "lib/log/log.h" #include "lib/malloc/malloc.h" #include "lib/sandbox/sandbox.h" #include "lib/string/printf.h" #include <stdbool.h> #include <errno.h> static smartlist_t *config_get_file_list(const char *path, smartlist_t *opened_files); Loading Loading @@ -52,21 +54,26 @@ config_get_lines_include(const char *string, config_line_t **result, opened_lst, 1, NULL, config_process_include); } /** Returns a list of paths obtained when expading globs in <b>pattern</b>. If * <b>pattern</b> has no globs, returns a list with <b>pattern</b> if it is an * existing path or NULL otherwise. If <b>opened_files</b> is provided, adds * paths opened by glob to it. Returns NULL on failure. */ /** Return a list of paths obtained when expading globs in <b>pattern</b>. * If <b>pattern</b> has no globs, return a list with <b>pattern</b> in it. * If <b>opened_files</b> is provided, add paths opened by glob to it. * Return NULL on failure. */ static smartlist_t * expand_glob(const char *pattern, smartlist_t *opened_files) { if (! has_glob(pattern)) { smartlist_t *matches = smartlist_new(); smartlist_add_strdup(matches, pattern); return matches; } smartlist_t *matches = tor_glob(pattern); if (!matches) { return NULL; if (errno == EPERM) { log_err(LD_CONFIG, "Sandbox is active, but the configuration pattern " "\"%s\" listed with %%include would access files or folders not " "allowed by it. Cannot proceed.", pattern); } // if it is not a glob, return error when the path is missing if (!has_glob(pattern) && smartlist_len(matches) == 0) { smartlist_free(matches); return NULL; } Loading Loading @@ -107,6 +114,13 @@ config_get_file_list(const char *pattern, smartlist_t *opened_files) if (opened_files) { smartlist_add_strdup(opened_files, path); } if (sandbox_interned_string_is_missing(path)) { log_err(LD_CONFIG, "Sandbox is active, but a new configuration " "file \"%s\" has been listed with %%include. Cannot proceed.", path); error_found = true; break; } file_status_t file_type = file_status(path); if (file_type == FN_FILE) { Loading Loading @@ -201,6 +215,13 @@ config_process_include(const char *pattern, int recursion_level, int extended, int rv = -1; SMARTLIST_FOREACH_BEGIN(config_files, const char *, config_file) { if (sandbox_interned_string_is_missing(config_file)) { log_err(LD_CONFIG, "Sandbox is active, but a new configuration " "file \"%s\" has been listed with %%include. Cannot proceed.", config_file); goto done; } log_notice(LD_CONFIG, "Including configuration file \"%s\".", config_file); config_line_t *included_config = NULL; config_line_t *included_config_last = NULL; Loading
src/lib/fs/path.c +14 −1 Original line number Diff line number Diff line Loading @@ -537,6 +537,10 @@ unglob_win32(const char *pattern, int prev_sep, int next_sep) static DIR * prot_opendir(const char *name) { if (sandbox_interned_string_is_missing(name)) { errno = EPERM; return NULL; } return opendir(sandbox_intern_string(name)); } Loading @@ -544,6 +548,10 @@ prot_opendir(const char *name) static int prot_stat(const char *pathname, struct stat *buf) { if (sandbox_interned_string_is_missing(pathname)) { errno = EPERM; return -1; } return stat(sandbox_intern_string(pathname), buf); } Loading @@ -551,6 +559,10 @@ prot_stat(const char *pathname, struct stat *buf) static int prot_lstat(const char *pathname, struct stat *buf) { if (sandbox_interned_string_is_missing(pathname)) { errno = EPERM; return -1; } return lstat(sandbox_intern_string(pathname), buf); } /** As closedir, but has the right type for gl_closedir */ Loading @@ -563,7 +575,8 @@ wrap_closedir(void *arg) /** Return a new list containing the paths that match the pattern * <b>pattern</b>. Return NULL on error. On POSIX systems, errno is set by the * glob function. * glob function or is set to EPERM if glob tried to access a file not allowed * by the seccomp sandbox. */ struct smartlist_t * tor_glob(const char *pattern) Loading
src/lib/sandbox/sandbox.c +36 −3 Original line number Diff line number Diff line Loading @@ -310,6 +310,8 @@ static int filter_nopar_gen[] = { #define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4) \ seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4)) static const char *sandbox_get_interned_string(const char *str); /** * Function responsible for setting up the rt_sigaction syscall for * the seccomp filter sandbox. Loading Loading @@ -1224,8 +1226,41 @@ static sandbox_filter_func_t filter_func[] = { sb_kill }; /** * Return the interned (and hopefully sandbox-permitted) string equal * to @a str. * * Return NULL if `str` is NULL, or `str` is not an interned string. **/ const char * sandbox_intern_string(const char *str) { const char *interned = sandbox_get_interned_string(str); if (sandbox_active && str != NULL && interned == NULL) { log_warn(LD_BUG, "No interned sandbox parameter found for %s", str); } return interned ? interned : str; } /** * Return true if the sandbox is running and we are missing an interned string * equal to @a str. */ bool sandbox_interned_string_is_missing(const char *str) { return sandbox_active && sandbox_get_interned_string(str) == NULL; } /** * Try to find and return the interned string equal to @a str. * * If there is no such string, return NULL. **/ static const char * sandbox_get_interned_string(const char *str) { sandbox_cfg_t *elem; Loading @@ -1245,9 +1280,7 @@ sandbox_intern_string(const char *str) } } if (sandbox_active) log_warn(LD_BUG, "No interned sandbox parameter found for %s", str); return str; return NULL; } /* DOCDOC */ Loading
src/lib/sandbox/sandbox.h +2 −3 Original line number Diff line number Diff line Loading @@ -104,12 +104,11 @@ typedef struct { #endif /* defined(USE_LIBSECCOMP) */ #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); bool sandbox_interned_string_is_missing(const char *s); #else /* !defined(USE_LIBSECCOMP) */ #define sandbox_intern_string(s) (s) #define sandbox_interned_string_is_missing(s) (false) #endif /* defined(USE_LIBSECCOMP) */ /** Creates an empty sandbox configuration file.*/ Loading