diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/crypt_ops/compat_openssl.h | 22 | ||||
-rw-r--r-- | src/lib/crypt_ops/crypto_openssl_mgt.h | 3 | ||||
-rw-r--r-- | src/lib/crypt_ops/crypto_rsa_openssl.c | 8 | ||||
-rw-r--r-- | src/lib/dispatch/dispatch_cfg_st.h | 4 | ||||
-rw-r--r-- | src/lib/geoip/geoip.c | 4 | ||||
-rw-r--r-- | src/lib/geoip/geoip.h | 6 | ||||
-rw-r--r-- | src/lib/malloc/malloc.h | 4 | ||||
-rw-r--r-- | src/lib/sandbox/sandbox.c | 128 |
8 files changed, 142 insertions, 37 deletions
diff --git a/src/lib/crypt_ops/compat_openssl.h b/src/lib/crypt_ops/compat_openssl.h index 0f56f338b5..c5eccdb015 100644 --- a/src/lib/crypt_ops/compat_openssl.h +++ b/src/lib/crypt_ops/compat_openssl.h @@ -20,32 +20,36 @@ * \brief compatibility definitions for working with different openssl forks **/ -#if !defined(LIBRESSL_VERSION_NUMBER) && \ - OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,1) +#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(1,0,1) #error "We require OpenSSL >= 1.0.1" #endif -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) && \ - ! defined(LIBRESSL_VERSION_NUMBER) +#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) /* We define this macro if we're trying to build with the majorly refactored * API in OpenSSL 1.1 */ #define OPENSSL_1_1_API #endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,0) && ... */ -#ifndef OPENSSL_1_1_API -#define OpenSSL_version(v) SSLeay_version(v) -#define tor_OpenSSL_version_num() SSLeay() +/* LibreSSL claims to be OpenSSL 2.0 but lacks these OpenSSL 1.1 APIs */ +#if !defined(OPENSSL_1_1_API) || defined(LIBRESSL_VERSION_NUMBER) #define RAND_OpenSSL() RAND_SSLeay() #define STATE_IS_SW_SERVER_HELLO(st) \ (((st) == SSL3_ST_SW_SRVR_HELLO_A) || \ ((st) == SSL3_ST_SW_SRVR_HELLO_B)) #define OSSL_HANDSHAKE_STATE int #define CONST_IF_OPENSSL_1_1_API -#else /* defined(OPENSSL_1_1_API) */ -#define tor_OpenSSL_version_num() OpenSSL_version_num() +#else #define STATE_IS_SW_SERVER_HELLO(st) \ ((st) == TLS_ST_SW_SRVR_HELLO) #define CONST_IF_OPENSSL_1_1_API const +#endif + +/* OpenSSL 1.1 and LibreSSL both have these APIs */ +#ifndef OPENSSL_1_1_API +#define OpenSSL_version(v) SSLeay_version(v) +#define tor_OpenSSL_version_num() SSLeay() +#else /* defined(OPENSSL_1_1_API) */ +#define tor_OpenSSL_version_num() OpenSSL_version_num() #endif /* !defined(OPENSSL_1_1_API) */ #endif /* defined(ENABLE_OPENSSL) */ diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.h b/src/lib/crypt_ops/crypto_openssl_mgt.h index c6f63ffa08..96a37721dd 100644 --- a/src/lib/crypt_ops/crypto_openssl_mgt.h +++ b/src/lib/crypt_ops/crypto_openssl_mgt.h @@ -54,8 +54,7 @@ #define DISABLE_ENGINES #endif -#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) && \ - !defined(LIBRESSL_VERSION_NUMBER) +#if OPENSSL_VERSION_NUMBER >= OPENSSL_VER(1,1,0,0,5) /* OpenSSL as of 1.1.0pre4 has an "new" thread API, which doesn't require * setting up various callbacks. * diff --git a/src/lib/crypt_ops/crypto_rsa_openssl.c b/src/lib/crypt_ops/crypto_rsa_openssl.c index a21c4a65cf..544d72e6ca 100644 --- a/src/lib/crypt_ops/crypto_rsa_openssl.c +++ b/src/lib/crypt_ops/crypto_rsa_openssl.c @@ -572,7 +572,9 @@ static bool rsa_private_key_too_long(RSA *rsa, int max_bits) { const BIGNUM *n, *e, *p, *q, *d, *dmp1, *dmq1, *iqmp; -#ifdef OPENSSL_1_1_API +#if defined(OPENSSL_1_1_API) && \ + (!defined(LIBRESSL_VERSION_NUMBER) || \ + LIBRESSL_VERSION_NUMBER >= OPENSSL_V_SERIES(3,5,0)) #if OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,1,1) n = RSA_get0_n(rsa); @@ -591,7 +593,7 @@ rsa_private_key_too_long(RSA *rsa, int max_bits) if (RSA_bits(rsa) > max_bits) return true; -#else /* !defined(OPENSSL_1_1_API) */ +#else /* !defined(OPENSSL_1_1_API) && ... */ n = rsa->n; e = rsa->e; p = rsa->p; @@ -600,7 +602,7 @@ rsa_private_key_too_long(RSA *rsa, int max_bits) dmp1 = rsa->dmp1; dmq1 = rsa->dmq1; iqmp = rsa->iqmp; -#endif /* defined(OPENSSL_1_1_API) */ +#endif /* defined(OPENSSL_1_1_API) && ... */ if (n && BN_num_bits(n) > max_bits) return true; diff --git a/src/lib/dispatch/dispatch_cfg_st.h b/src/lib/dispatch/dispatch_cfg_st.h index 636f2e6df5..503d13e010 100644 --- a/src/lib/dispatch/dispatch_cfg_st.h +++ b/src/lib/dispatch/dispatch_cfg_st.h @@ -24,9 +24,9 @@ struct dispatch_cfg_t { struct smartlist_t *type_by_msg; /** A list of channel_id_t (cast to void*), indexed by msg_t. */ struct smartlist_t *chan_by_msg; - /** A list of dispatch_rcv_t, indexed by msg_type_id_t. */ + /** A list of dispatch_typefns_t, indexed by msg_type_id_t. */ struct smartlist_t *fns_by_type; - /** A list of dispatch_typefns_t, indexed by msg_t. */ + /** A list of dispatch_rcv_t, indexed by msg_t. */ struct smartlist_t *recv_by_msg; }; diff --git a/src/lib/geoip/geoip.c b/src/lib/geoip/geoip.c index 686040613d..f13354dbe1 100644 --- a/src/lib/geoip/geoip.c +++ b/src/lib/geoip/geoip.c @@ -387,7 +387,7 @@ geoip_load_file(sa_family_t family, const char *filename, int severity) * be less than geoip_get_n_countries(). To decode it, call * geoip_get_country_name(). */ -int +STATIC int geoip_get_country_by_ipv4(uint32_t ipaddr) { geoip_ipv4_entry_t *ent; @@ -403,7 +403,7 @@ geoip_get_country_by_ipv4(uint32_t ipaddr) * 0 for the 'unknown country'. The return value will always be less than * geoip_get_n_countries(). To decode it, call geoip_get_country_name(). */ -int +STATIC int geoip_get_country_by_ipv6(const struct in6_addr *addr) { geoip_ipv6_entry_t *ent; diff --git a/src/lib/geoip/geoip.h b/src/lib/geoip/geoip.h index 764ed1d5a5..e68573fd1a 100644 --- a/src/lib/geoip/geoip.h +++ b/src/lib/geoip/geoip.h @@ -21,14 +21,14 @@ #ifdef GEOIP_PRIVATE STATIC int geoip_parse_entry(const char *line, sa_family_t family); STATIC void clear_geoip_db(void); + +STATIC int geoip_get_country_by_ipv4(uint32_t ipaddr); +STATIC int geoip_get_country_by_ipv6(const struct in6_addr *addr); #endif /* defined(GEOIP_PRIVATE) */ struct in6_addr; struct tor_addr_t; -int geoip_get_country_by_ipv4(uint32_t ipaddr); -int geoip_get_country_by_ipv6(const struct in6_addr *addr); - /** A per-country GeoIP record. */ typedef struct geoip_country_t { /** A nul-terminated two-letter country-code. */ diff --git a/src/lib/malloc/malloc.h b/src/lib/malloc/malloc.h index cc031f843a..48a3ac32cf 100644 --- a/src/lib/malloc/malloc.h +++ b/src/lib/malloc/malloc.h @@ -11,6 +11,7 @@ #ifndef TOR_UTIL_MALLOC_H #define TOR_UTIL_MALLOC_H +#include <assert.h> #include <stddef.h> #include <stdlib.h> #include "lib/cc/compat_compiler.h" @@ -45,6 +46,9 @@ void tor_free_(void *mem); #ifdef __GNUC__ #define tor_free(p) STMT_BEGIN \ typeof(&(p)) tor_free__tmpvar = &(p); \ + _Static_assert(!__builtin_types_compatible_p(typeof(*tor_free__tmpvar), \ + struct event *), \ + "use tor_event_free for struct event *"); \ raw_free(*tor_free__tmpvar); \ *tor_free__tmpvar=NULL; \ STMT_END diff --git a/src/lib/sandbox/sandbox.c b/src/lib/sandbox/sandbox.c index cc00d2048f..7c024d7e37 100644 --- a/src/lib/sandbox/sandbox.c +++ b/src/lib/sandbox/sandbox.c @@ -141,10 +141,12 @@ static sandbox_cfg_t *filter_dynamic = NULL; * the high bits of the value might get masked out improperly. */ #define SCMP_CMP_MASKED(a,b,c) \ SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c)) -/* For negative constants, the rule to add depends on the glibc version. */ -#define SCMP_CMP_NEG(a,op,b) (libc_negative_constant_needs_cast() ? \ - (SCMP_CMP((a), (op), (unsigned int)(b))) : \ - (SCMP_CMP_STR((a), (op), (b)))) +/* Negative constants aren't consistently sign extended or zero extended. + * Different compilers, libc, and architectures behave differently. For cases + * where the kernel ABI uses a 32 bit integer, this macro can be used to + * mask-compare only the lower 32 bits of the value. */ +#define SCMP_CMP_LOWER32_EQ(a,b) \ + SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, 0xFFFFFFFF, (unsigned int)(b)) /** Variable used for storing all syscall numbers that will be allowed with the * stage 1 general Tor sandbox. @@ -516,14 +518,6 @@ libc_uses_openat_for_opendir(void) (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 - * negative arguments like AT_FDCWD for seccomp rules. */ -static int -libc_negative_constant_needs_cast(void) -{ - return is_libc_at_least(2, 27); -} - /** 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 @@ -531,7 +525,7 @@ 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_NEG(0, SCMP_CMP_EQ, AT_FDCWD), + SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), SCMP_CMP_STR(1, SCMP_CMP_EQ, file)); } else { return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), @@ -612,6 +606,32 @@ sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter) return 0; } +static int +sb_fchmodat(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(fchmodat)) { + rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmodat), + SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), + SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add fchmodat syscall, received " + "libseccomp error %d", rc); + return rc; + } + } + } + + return 0; +} + #ifdef __i386__ static int sb_chown32(scmp_filter_ctx ctx, sandbox_cfg_t *filter) @@ -664,6 +684,32 @@ sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } #endif /* defined(__i386__) */ +static int +sb_fchownat(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(fchownat)) { + rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchownat), + SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), + SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add fchownat syscall, received " + "libseccomp error %d", rc); + return rc; + } + } + } + + return 0; +} + /** * Function responsible for setting up the rename syscall for * the seccomp filter sandbox. @@ -696,6 +742,39 @@ sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter) } /** + * Function responsible for setting up the renameat syscall for + * the seccomp filter sandbox. + */ +static int +sb_renameat(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(renameat)) { + + rc = seccomp_rule_add_4(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat), + SCMP_CMP_LOWER32_EQ(0, AT_FDCWD), + SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value), + SCMP_CMP_LOWER32_EQ(2, AT_FDCWD), + SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2)); + if (rc != 0) { + log_err(LD_BUG,"(Sandbox) failed to add renameat syscall, received " + "libseccomp error %d", rc); + return rc; + } + } + } + + return 0; +} + +/** * Function responsible for setting up the openat syscall for * the seccomp filter sandbox. */ @@ -712,7 +791,7 @@ sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter) if (param != NULL && param->prot == 1 && param->syscall == SCMP_SYS(openat)) { rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), - SCMP_CMP_NEG(0, SCMP_CMP_EQ, AT_FDCWD), + SCMP_CMP_LOWER32_EQ(0, 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)); @@ -1315,7 +1394,9 @@ static sandbox_filter_func_t filter_func[] = { #else sb_chown, #endif + sb_fchownat, sb_chmod, + sb_fchmodat, sb_open, sb_openat, sb_opendir, @@ -1323,6 +1404,7 @@ static sandbox_filter_func_t filter_func[] = { sb_ptrace, #endif sb_rename, + sb_renameat, #ifdef __NR_fcntl64 sb_fcntl64, #endif @@ -1590,10 +1672,24 @@ new_element(int syscall, char *value) #ifdef __i386__ #define SCMP_chown SCMP_SYS(chown32) +#elif defined(__aarch64__) && defined(__LP64__) +#define SCMP_chown SCMP_SYS(fchownat) #else #define SCMP_chown SCMP_SYS(chown) #endif +#if defined(__aarch64__) && defined(__LP64__) +#define SCMP_chmod SCMP_SYS(fchmodat) +#else +#define SCMP_chmod SCMP_SYS(chmod) +#endif + +#if defined(__aarch64__) && defined(__LP64__) +#define SCMP_rename SCMP_SYS(renameat) +#else +#define SCMP_rename SCMP_SYS(rename) +#endif + #ifdef __NR_stat64 #define SCMP_stat SCMP_SYS(stat64) #else @@ -1631,7 +1727,7 @@ sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file) { sandbox_cfg_t *elem = NULL; - elem = new_element(SCMP_SYS(chmod), file); + elem = new_element(SCMP_chmod, file); elem->next = *cfg; *cfg = elem; @@ -1657,7 +1753,7 @@ sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2) { sandbox_cfg_t *elem = NULL; - elem = new_element2(SCMP_SYS(rename), file1, file2); + elem = new_element2(SCMP_rename, file1, file2); elem->next = *cfg; *cfg = elem; |