mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 13:13:44 +01:00
Merge remote-tracking branch 'tor-gitlab/mr/68' into maint-0.4.4
This commit is contained in:
commit
5cd85feaa7
9
changes/bug40020
Normal file
9
changes/bug40020
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
o Minor bugfixes (linux seccomp2 sandbox):
|
||||||
|
- Makes the seccomp sandbox allow the correct syscall for opendir
|
||||||
|
according to the running glibc version. The opendir function
|
||||||
|
either uses open or openat but the current code does not
|
||||||
|
differenciate between opendir and open calls. This adds a new
|
||||||
|
seccomp sandbox rule for opendir. This fixes crashes when
|
||||||
|
reloading torrc with sandbox enabled when running on glibc
|
||||||
|
2.15 to 2.21 and 2.26. Patch from Daniel Pinto. Fixes bug 40020;
|
||||||
|
bugfix on 0.3.5.11.
|
@ -822,6 +822,9 @@ sandbox_init_filter(void)
|
|||||||
#define OPEN(name) \
|
#define OPEN(name) \
|
||||||
sandbox_cfg_allow_open_filename(&cfg, tor_strdup(name))
|
sandbox_cfg_allow_open_filename(&cfg, tor_strdup(name))
|
||||||
|
|
||||||
|
#define OPENDIR(dir) \
|
||||||
|
sandbox_cfg_allow_opendir_dirname(&cfg, tor_strdup(dir))
|
||||||
|
|
||||||
#define OPEN_DATADIR(name) \
|
#define OPEN_DATADIR(name) \
|
||||||
sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname(name))
|
sandbox_cfg_allow_open_filename(&cfg, get_datadir_fname(name))
|
||||||
|
|
||||||
@ -839,7 +842,7 @@ sandbox_init_filter(void)
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define OPEN_KEY_DIRECTORY() \
|
#define OPEN_KEY_DIRECTORY() \
|
||||||
sandbox_cfg_allow_open_filename(&cfg, tor_strdup(options->KeyDirectory))
|
OPENDIR(options->KeyDirectory)
|
||||||
#define OPEN_CACHEDIR(name) \
|
#define OPEN_CACHEDIR(name) \
|
||||||
sandbox_cfg_allow_open_filename(&cfg, get_cachedir_fname(name))
|
sandbox_cfg_allow_open_filename(&cfg, get_cachedir_fname(name))
|
||||||
#define OPEN_CACHEDIR_SUFFIX(name, suffix) do { \
|
#define OPEN_CACHEDIR_SUFFIX(name, suffix) do { \
|
||||||
@ -853,7 +856,7 @@ sandbox_init_filter(void)
|
|||||||
OPEN_KEYDIR(name suffix); \
|
OPEN_KEYDIR(name suffix); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
OPEN(options->DataDirectory);
|
OPENDIR(options->DataDirectory);
|
||||||
OPEN_KEY_DIRECTORY();
|
OPEN_KEY_DIRECTORY();
|
||||||
|
|
||||||
OPEN_CACHEDIR_SUFFIX("cached-certs", ".tmp");
|
OPEN_CACHEDIR_SUFFIX("cached-certs", ".tmp");
|
||||||
@ -900,7 +903,11 @@ sandbox_init_filter(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SMARTLIST_FOREACH(options->FilesOpenedByIncludes, char *, f, {
|
SMARTLIST_FOREACH(options->FilesOpenedByIncludes, char *, f, {
|
||||||
OPEN(f);
|
if (file_status(f) == FN_DIR) {
|
||||||
|
OPENDIR(f);
|
||||||
|
} else {
|
||||||
|
OPEN(f);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
#define RENAME_SUFFIX(name, suffix) \
|
#define RENAME_SUFFIX(name, suffix) \
|
||||||
@ -1013,7 +1020,7 @@ sandbox_init_filter(void)
|
|||||||
* directory that holds it. */
|
* directory that holds it. */
|
||||||
char *dirname = tor_strdup(port->unix_addr);
|
char *dirname = tor_strdup(port->unix_addr);
|
||||||
if (get_parent_directory(dirname) == 0) {
|
if (get_parent_directory(dirname) == 0) {
|
||||||
OPEN(dirname);
|
OPENDIR(dirname);
|
||||||
}
|
}
|
||||||
tor_free(dirname);
|
tor_free(dirname);
|
||||||
sandbox_cfg_allow_chmod_filename(&cfg, tor_strdup(port->unix_addr));
|
sandbox_cfg_allow_chmod_filename(&cfg, tor_strdup(port->unix_addr));
|
||||||
|
@ -289,6 +289,12 @@ static int filter_nopar_gen[] = {
|
|||||||
SCMP_SYS(poll)
|
SCMP_SYS(poll)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* opendir is not a syscall but it will use either open or openat. We do not
|
||||||
|
* want the decision to allow open/openat to be the callers reponsability, so
|
||||||
|
* we create a phony syscall number for opendir and sb_opendir will choose the
|
||||||
|
* correct syscall. */
|
||||||
|
#define PHONY_OPENDIR_SYSCALL -2
|
||||||
|
|
||||||
/* These macros help avoid the error where the number of filters we add on a
|
/* These macros help avoid the error where the number of filters we add on a
|
||||||
* single rule don't match the arg_cnt param. */
|
* single rule don't match the arg_cnt param. */
|
||||||
#define seccomp_rule_add_0(ctx,act,call) \
|
#define seccomp_rule_add_0(ctx,act,call) \
|
||||||
@ -469,14 +475,24 @@ is_libc_at_least(int major, int minor)
|
|||||||
#endif /* defined(CHECK_LIBC_VERSION) */
|
#endif /* defined(CHECK_LIBC_VERSION) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if we think we're running with a libc that always uses
|
/* Return true if we think we're running with a libc that uses openat for the
|
||||||
* openat on linux. */
|
* open function on linux. */
|
||||||
static int
|
static int
|
||||||
libc_uses_openat_for_everything(void)
|
libc_uses_openat_for_open(void)
|
||||||
{
|
{
|
||||||
return is_libc_at_least(2, 26);
|
return is_libc_at_least(2, 26);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if we think we're running with a libc that uses openat for the
|
||||||
|
* opendir function on linux. */
|
||||||
|
static int
|
||||||
|
libc_uses_openat_for_opendir(void)
|
||||||
|
{
|
||||||
|
// libc 2.27 and above or between 2.15 (inclusive) and 2.22 (exclusive)
|
||||||
|
return is_libc_at_least(2, 27) ||
|
||||||
|
(is_libc_at_least(2, 15) && !is_libc_at_least(2, 22));
|
||||||
|
}
|
||||||
|
|
||||||
/* Return true if we think we're running with a libc that needs to cast
|
/* Return true if we think we're running with a libc that needs to cast
|
||||||
* negative arguments like AT_FDCWD for seccomp rules. */
|
* negative arguments like AT_FDCWD for seccomp rules. */
|
||||||
static int
|
static int
|
||||||
@ -510,7 +526,7 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
|
|||||||
int rc;
|
int rc;
|
||||||
sandbox_cfg_t *elem = NULL;
|
sandbox_cfg_t *elem = NULL;
|
||||||
|
|
||||||
int use_openat = libc_uses_openat_for_everything();
|
int use_openat = libc_uses_openat_for_open();
|
||||||
|
|
||||||
// for each dynamic parameter filters
|
// for each dynamic parameter filters
|
||||||
for (elem = filter; elem != NULL; elem = elem->next) {
|
for (elem = filter; elem != NULL; elem = elem->next) {
|
||||||
@ -643,6 +659,38 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sb_opendir(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
|
||||||
|
== PHONY_OPENDIR_SYSCALL) {
|
||||||
|
if (libc_uses_openat_for_opendir()) {
|
||||||
|
rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
|
||||||
|
SCMP_CMP_NEG(0, SCMP_CMP_EQ, AT_FDCWD),
|
||||||
|
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));
|
||||||
|
} else {
|
||||||
|
rc = allow_file_open(ctx, 0, param->value);
|
||||||
|
}
|
||||||
|
if (rc != 0) {
|
||||||
|
log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
|
||||||
|
"libseccomp error %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function responsible for setting up the socket syscall for
|
* Function responsible for setting up the socket syscall for
|
||||||
* the seccomp filter sandbox.
|
* the seccomp filter sandbox.
|
||||||
@ -1157,6 +1205,7 @@ static sandbox_filter_func_t filter_func[] = {
|
|||||||
sb_chmod,
|
sb_chmod,
|
||||||
sb_open,
|
sb_open,
|
||||||
sb_openat,
|
sb_openat,
|
||||||
|
sb_opendir,
|
||||||
sb_rename,
|
sb_rename,
|
||||||
#ifdef __NR_fcntl64
|
#ifdef __NR_fcntl64
|
||||||
sb_fcntl64,
|
sb_fcntl64,
|
||||||
@ -1476,6 +1525,19 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sandbox_cfg_allow_opendir_dirname(sandbox_cfg_t **cfg, char *dir)
|
||||||
|
{
|
||||||
|
sandbox_cfg_t *elem = NULL;
|
||||||
|
|
||||||
|
elem = new_element(PHONY_OPENDIR_SYSCALL, dir);
|
||||||
|
|
||||||
|
elem->next = *cfg;
|
||||||
|
*cfg = elem;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function responsible for going through the parameter syscall filters and
|
* Function responsible for going through the parameter syscall filters and
|
||||||
* call each function pointer in the list.
|
* call each function pointer in the list.
|
||||||
@ -1803,6 +1865,13 @@ sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sandbox_cfg_allow_opendir_dirname(sandbox_cfg_t **cfg, char *dir)
|
||||||
|
{
|
||||||
|
(void)cfg; (void)dir;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
|
sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
|
||||||
{
|
{
|
||||||
|
@ -135,6 +135,13 @@ int sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2);
|
|||||||
*/
|
*/
|
||||||
int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file);
|
int sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function used to add a opendir allowed filename to a supplied configuration.
|
||||||
|
* The (char*) specifies the path to the allowed dir; we steal the pointer to
|
||||||
|
* that dir.
|
||||||
|
*/
|
||||||
|
int sandbox_cfg_allow_opendir_dirname(sandbox_cfg_t **cfg, char *dir);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function used to add a stat/stat64 allowed filename to a configuration.
|
* Function used to add a stat/stat64 allowed filename to a configuration.
|
||||||
* The (char*) specifies the path to the allowed file; that pointer is stolen.
|
* The (char*) specifies the path to the allowed file; that pointer is stolen.
|
||||||
|
Loading…
Reference in New Issue
Block a user