diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/address.c | 18 | ||||
-rw-r--r-- | src/common/buffers.h | 1 | ||||
-rw-r--r-- | src/common/compat.c | 46 | ||||
-rw-r--r-- | src/common/compat.h | 6 | ||||
-rw-r--r-- | src/common/compat_winthreads.c | 1 | ||||
-rw-r--r-- | src/common/compress.c | 10 | ||||
-rw-r--r-- | src/common/compress.h | 1 | ||||
-rw-r--r-- | src/common/compress_zstd.c | 112 | ||||
-rw-r--r-- | src/common/compress_zstd.h | 7 | ||||
-rw-r--r-- | src/common/crypto.c | 24 | ||||
-rw-r--r-- | src/common/crypto.h | 11 | ||||
-rw-r--r-- | src/common/log.c | 31 | ||||
-rw-r--r-- | src/common/torlog.h | 14 | ||||
-rw-r--r-- | src/common/util.h | 18 |
14 files changed, 243 insertions, 57 deletions
diff --git a/src/common/address.c b/src/common/address.c index a2f4c93b91..ca263425f0 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -1697,7 +1697,7 @@ get_interface_address6_via_udp_socket_hack,(int severity, sa_family_t family, tor_addr_t *addr)) { - struct sockaddr_storage my_addr, target_addr; + struct sockaddr_storage target_addr; int sock=-1, r=-1; socklen_t addr_len; @@ -1740,21 +1740,19 @@ get_interface_address6_via_udp_socket_hack,(int severity, goto err; } - if (tor_getsockname(sock,(struct sockaddr*)&my_addr, &addr_len)) { + if (tor_addr_from_getsockname(addr, sock) < 0) { int e = tor_socket_errno(sock); log_fn(severity, LD_NET, "getsockname() to determine interface failed: %s", tor_socket_strerror(e)); goto err; } - if (tor_addr_from_sockaddr(addr, (struct sockaddr*)&my_addr, NULL) == 0) { - if (tor_addr_is_loopback(addr) || tor_addr_is_multicast(addr)) { - log_fn(severity, LD_NET, "Address that we determined via UDP socket" - " magic is unsuitable for public comms."); - } else { - r=0; - } - } + if (tor_addr_is_loopback(addr) || tor_addr_is_multicast(addr)) { + log_fn(severity, LD_NET, "Address that we determined via UDP socket" + " magic is unsuitable for public comms."); + } else { + r=0; + } err: if (sock >= 0) diff --git a/src/common/buffers.h b/src/common/buffers.h index 22a5f7bfa3..4275152de2 100644 --- a/src/common/buffers.h +++ b/src/common/buffers.h @@ -13,7 +13,6 @@ #define TOR_BUFFERS_H #include "compat.h" -#include "compat.h" #include "torint.h" #include "testsupport.h" diff --git a/src/common/compat.c b/src/common/compat.c index 4cb346dfa5..99a7b8c0c1 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -100,7 +100,6 @@ SecureZeroMemory(PVOID ptr, SIZE_T cnt) /* Only use the linux prctl; the IRIX prctl is totally different */ #include <sys/prctl.h> #elif defined(__APPLE__) -#include <sys/types.h> #include <sys/ptrace.h> #endif /* defined(HAVE_SYS_PRCTL_H) && defined(__linux__) || ... */ @@ -116,7 +115,7 @@ SecureZeroMemory(PVOID ptr, SIZE_T cnt) #ifdef HAVE_SIGNAL_H #include <signal.h> #endif -#ifdef HAVE_SYS_MMAN_H +#ifdef HAVE_MMAP #include <sys/mman.h> #endif #ifdef HAVE_SYS_SYSLIMITS_H @@ -204,25 +203,17 @@ tor_rename(const char *path_old, const char *path_new) sandbox_intern_string(path_new)); } -/* Some MinGW builds have sys/mman.h, but not the corresponding symbols. - * Other configs rename the symbols using macros (including getpagesize). - * So check for sys/mman.h and unistd.h, and a getpagesize declaration. */ -#if (defined(HAVE_SYS_MMAN_H) && defined(HAVE_UNISTD_H) && \ - defined(HAVE_DECL_GETPAGESIZE)) -#define COMPAT_HAS_MMAN_AND_PAGESIZE -#endif - -#if defined(COMPAT_HAS_MMAN_AND_PAGESIZE) || \ - defined(RUNNING_DOXYGEN) +#if defined(HAVE_MMAP) || defined(RUNNING_DOXYGEN) /** Try to create a memory mapping for <b>filename</b> and return it. On - * failure, return NULL. Sets errno properly, using ERANGE to mean - * "empty file". */ + * failure, return NULL. Sets errno properly, using ERANGE to mean + * "empty file". Must only be called on trusted Tor-owned files, as changing + * the underlying file's size causes unspecified behavior. */ tor_mmap_t * tor_mmap_file(const char *filename) { int fd; /* router file */ char *string; - int page_size, result; + int result; tor_mmap_t *res; size_t size, filesize; struct stat st; @@ -251,13 +242,6 @@ tor_mmap_file(const char *filename) return NULL; } size = filesize = (size_t)(st.st_size); - /* - * Should we check for weird crap like mmapping a named pipe here, - * or just wait for if (!size) below to fail? - */ - /* ensure page alignment */ - page_size = getpagesize(); - size += (size%page_size) ? page_size-(size%page_size) : 0; if (st.st_size > SSIZE_T_CEILING || (off_t)size < st.st_size) { log_warn(LD_FS, "File \"%s\" is too large. Ignoring.",filename); @@ -1392,6 +1376,24 @@ tor_getsockname,(tor_socket_t sock, struct sockaddr *address, return getsockname(sock, address, address_len); } +/** + * Find the local address associated with the socket <b>sock</b>, and + * place it in *<b>addr_out</b>. Return 0 on success, -1 on failure. + * + * (As tor_getsockname, but instead places the result in a tor_addr_t.) */ +int +tor_addr_from_getsockname(tor_addr_t *addr_out, tor_socket_t sock) +{ + struct sockaddr_storage ss; + socklen_t ss_len = sizeof(ss); + memset(&ss, 0, sizeof(ss)); + + if (tor_getsockname(sock, (struct sockaddr *) &ss, &ss_len) < 0) + return -1; + + return tor_addr_from_sockaddr(addr_out, (struct sockaddr *)&ss, NULL); +} + /** Turn <b>socket</b> into a nonblocking socket. Return 0 on success, -1 * on failure. */ diff --git a/src/common/compat.h b/src/common/compat.h index 93301feda0..1bdff8db3d 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -318,12 +318,12 @@ typedef struct tor_mmap_t { size_t size; /**< Size of the file. */ /* None of the fields below should be accessed from outside compat.c */ -#ifdef HAVE_SYS_MMAN_H +#ifdef HAVE_MMAP size_t mapping_size; /**< Size of the actual mapping. (This is this file * size, rounded up to the nearest page.) */ #elif defined _WIN32 HANDLE mmap_handle; -#endif /* defined(HAVE_SYS_MMAN_H) || ... */ +#endif /* defined(HAVE_MMAP) || ... */ } tor_mmap_t; @@ -510,6 +510,8 @@ int get_n_open_sockets(void); MOCK_DECL(int, tor_getsockname,(tor_socket_t socket, struct sockaddr *address, socklen_t *address_len)); +struct tor_addr_t; +int tor_addr_from_getsockname(struct tor_addr_t *addr_out, tor_socket_t sock); #define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags) #define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags) diff --git a/src/common/compat_winthreads.c b/src/common/compat_winthreads.c index 5f7ec94c23..7021344f6e 100644 --- a/src/common/compat_winthreads.c +++ b/src/common/compat_winthreads.c @@ -18,7 +18,6 @@ #include "util.h" #include "container.h" #include "torlog.h" -#include <process.h> /* This value is more or less total cargo-cult */ #define SPIN_COUNT 2000 diff --git a/src/common/compress.c b/src/common/compress.c index 47c93cf6a9..cb1549f1aa 100644 --- a/src/common/compress.c +++ b/src/common/compress.c @@ -663,3 +663,13 @@ tor_compress_init(void) tor_zstd_init(); } +/** Warn if we had any problems while setting up our compression libraries. + * + * (This isn't part of tor_compress_init, since the logs aren't set up yet.) + */ +void +tor_compress_log_init_warnings(void) +{ + tor_zstd_warn_if_version_mismatched(); +} + diff --git a/src/common/compress.h b/src/common/compress.h index 952102bf97..65d63a4386 100644 --- a/src/common/compress.h +++ b/src/common/compress.h @@ -87,6 +87,7 @@ void tor_compress_free_(tor_compress_state_t *state); size_t tor_compress_state_size(const tor_compress_state_t *state); void tor_compress_init(void); +void tor_compress_log_init_warnings(void); #endif /* !defined(TOR_COMPRESS_H) */ diff --git a/src/common/compress_zstd.c b/src/common/compress_zstd.c index 0db87d61b7..4024f5594d 100644 --- a/src/common/compress_zstd.c +++ b/src/common/compress_zstd.c @@ -18,6 +18,13 @@ #include "compress.h" #include "compress_zstd.h" +#ifdef ENABLE_ZSTD_ADVANCED_APIS +/* This is a lie, but we make sure it doesn't get us in trouble by wrapping + * all invocations of zstd's static-only functions in a check to make sure + * that the compile-time version matches the run-time version. */ +#define ZSTD_STATIC_LINKING_ONLY +#endif + #ifdef HAVE_ZSTD #include <zstd.h> #endif @@ -51,21 +58,31 @@ tor_zstd_method_supported(void) #endif } +#ifdef HAVE_ZSTD +/** Format a zstd version number as a string in <b>buf</b>. */ +static void +tor_zstd_format_version(char *buf, size_t buflen, unsigned version_number) +{ + tor_snprintf(buf, buflen, + "%u.%u.%u", + version_number / 10000 % 100, + version_number / 100 % 100, + version_number % 100); +} +#endif + +#define VERSION_STR_MAX_LEN 16 /* more than enough space for 99.99.99 */ + /** Return a string representation of the version of the currently running * version of libzstd. Returns NULL if Zstandard is unsupported. */ const char * tor_zstd_get_version_str(void) { #ifdef HAVE_ZSTD - static char version_str[16]; - size_t version_number; + static char version_str[VERSION_STR_MAX_LEN]; - version_number = ZSTD_versionNumber(); - tor_snprintf(version_str, sizeof(version_str), - "%d.%d.%d", - (int) version_number / 10000 % 100, - (int) version_number / 100 % 100, - (int) version_number % 100); + tor_zstd_format_version(version_str, sizeof(version_str), + ZSTD_versionNumber()); return version_str; #else /* !(defined(HAVE_ZSTD)) */ @@ -85,6 +102,26 @@ tor_zstd_get_header_version_str(void) #endif } +#ifdef TOR_UNIT_TESTS +static int static_apis_disable_for_testing = 0; +#endif + +/** Return true iff we can use the "static-only" APIs. */ +int +tor_zstd_can_use_static_apis(void) +{ +#if defined(ZSTD_STATIC_LINKING_ONLY) && defined(HAVE_ZSTD) +#ifdef TOR_UNIT_TESTS + if (static_apis_disable_for_testing) { + return 0; + } +#endif + return (ZSTD_VERSION_NUMBER == ZSTD_versionNumber()); +#else + return 0; +#endif +} + /** Internal Zstandard state for incremental compression/decompression. * The body of this struct is not exposed. */ struct tor_zstd_compress_state_t { @@ -112,9 +149,11 @@ struct tor_zstd_compress_state_t { #ifdef HAVE_ZSTD /** Return an approximate number of bytes stored in memory to hold the - * Zstandard compression/decompression state. */ + * Zstandard compression/decompression state. This is a fake estimate + * based on inspecting the zstd source: tor_zstd_state_size_precalc() is + * more accurate when it's allowed to use "static-only" functions */ static size_t -tor_zstd_state_size_precalc(int compress, int preset) +tor_zstd_state_size_precalc_fake(int compress, int preset) { tor_assert(preset > 0); @@ -171,6 +210,28 @@ tor_zstd_state_size_precalc(int compress, int preset) return memory_usage; } + +/** Return an approximate number of bytes stored in memory to hold the + * Zstandard compression/decompression state. */ +static size_t +tor_zstd_state_size_precalc(int compress, int preset) +{ +#ifdef ZSTD_STATIC_LINKING_ONLY + if (tor_zstd_can_use_static_apis()) { + if (compress) { +#ifdef HAVE_ZSTD_ESTIMATECSTREAMSIZE + return ZSTD_estimateCStreamSize(preset); +#endif + } else { +#ifdef HAVE_ZSTD_ESTIMATEDCTXSIZE + /* Could use DStream, but that takes a windowSize. */ + return ZSTD_estimateDCtxSize(); +#endif + } + } +#endif + return tor_zstd_state_size_precalc_fake(compress, preset); +} #endif /* defined(HAVE_ZSTD) */ /** Construct and return a tor_zstd_compress_state_t object using @@ -440,3 +501,34 @@ tor_zstd_init(void) atomic_counter_init(&total_zstd_allocation); } +/** Warn if the header and library versions don't match. */ +void +tor_zstd_warn_if_version_mismatched(void) +{ +#if defined(HAVE_ZSTD) && defined(ENABLE_ZSTD_ADVANCED_APIS) + if (! tor_zstd_can_use_static_apis()) { + char header_version[VERSION_STR_MAX_LEN]; + char runtime_version[VERSION_STR_MAX_LEN]; + tor_zstd_format_version(header_version, sizeof(header_version), + ZSTD_VERSION_NUMBER); + tor_zstd_format_version(runtime_version, sizeof(runtime_version), + ZSTD_versionNumber()); + + log_warn(LD_GENERAL, + "Tor was compiled with zstd %s, but is running with zstd %s. " + "For safety, we'll avoid using advanced zstd functionality.", + header_version, runtime_version); + } +#endif +} + +#ifdef TOR_UNIT_TESTS +/** Testing only: disable usage of static-only APIs, so we can make sure that + * we still work without them. */ +void +tor_zstd_set_static_apis_disabled_for_testing(int disabled) +{ + static_apis_disable_for_testing = disabled; +} +#endif + diff --git a/src/common/compress_zstd.h b/src/common/compress_zstd.h index 9bca24ded7..bd42cf65ce 100644 --- a/src/common/compress_zstd.h +++ b/src/common/compress_zstd.h @@ -17,6 +17,8 @@ const char *tor_zstd_get_version_str(void); const char *tor_zstd_get_header_version_str(void); +int tor_zstd_can_use_static_apis(void); + /** Internal state for an incremental Zstandard compression/decompression. */ typedef struct tor_zstd_compress_state_t tor_zstd_compress_state_t; @@ -41,6 +43,11 @@ size_t tor_zstd_compress_state_size(const tor_zstd_compress_state_t *state); size_t tor_zstd_get_total_allocation(void); void tor_zstd_init(void); +void tor_zstd_warn_if_version_mismatched(void); + +#ifdef TOR_UNIT_TESTS +void tor_zstd_set_static_apis_disabled_for_testing(int disabled); +#endif #endif /* !defined(TOR_COMPRESS_ZSTD_H) */ diff --git a/src/common/crypto.c b/src/common/crypto.c index d85aca4004..ade8b0191f 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -970,6 +970,7 @@ crypto_digest_alloc_bytes(digest_algorithm_t alg) /* Gives the length of crypto_digest_t through the end of the field 'd' */ #define END_OF_FIELD(f) (offsetof(crypto_digest_t, f) + \ STRUCT_FIELD_SIZE(crypto_digest_t, f)) + switch (alg) { case DIGEST_SHA1: return END_OF_FIELD(d.sha1); @@ -1155,6 +1156,29 @@ crypto_digest_dup(const crypto_digest_t *digest) return tor_memdup(digest, alloc_bytes); } +/** Temporarily save the state of <b>digest</b> in <b>checkpoint</b>. + * Asserts that <b>digest</b> is a SHA1 digest object. + */ +void +crypto_digest_checkpoint(crypto_digest_checkpoint_t *checkpoint, + const crypto_digest_t *digest) +{ + const size_t bytes = crypto_digest_alloc_bytes(digest->algorithm); + tor_assert(bytes <= sizeof(checkpoint->mem)); + memcpy(checkpoint->mem, digest, bytes); +} + +/** Restore the state of <b>digest</b> from <b>checkpoint</b>. + * Asserts that <b>digest</b> is a SHA1 digest object. Requires that the + * state was previously stored with crypto_digest_checkpoint() */ +void +crypto_digest_restore(crypto_digest_t *digest, + const crypto_digest_checkpoint_t *checkpoint) +{ + const size_t bytes = crypto_digest_alloc_bytes(digest->algorithm); + memcpy(digest, checkpoint->mem, bytes); +} + /** Replace the state of the digest object <b>into</b> with the state * of the digest object <b>from</b>. Requires that 'into' and 'from' * have the same digest type. diff --git a/src/common/crypto.h b/src/common/crypto.h index a9c8837b9e..015c5fcfe7 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -90,6 +90,13 @@ typedef struct crypto_digest_t crypto_digest_t; typedef struct crypto_xof_t crypto_xof_t; typedef struct crypto_dh_t crypto_dh_t; +#define DIGEST_CHECKPOINT_BYTES (SIZEOF_VOID_P + 512) +/** Structure used to temporarily save the a digest object. Only implemented + * for SHA1 digest for now. */ +typedef struct crypto_digest_checkpoint_t { + uint8_t mem[DIGEST_CHECKPOINT_BYTES]; +} crypto_digest_checkpoint_t; + /* global state */ int crypto_early_init(void) ATTR_WUR; int crypto_global_init(int hardwareAccel, @@ -178,6 +185,10 @@ void crypto_digest_add_bytes(crypto_digest_t *digest, const char *data, void crypto_digest_get_digest(crypto_digest_t *digest, char *out, size_t out_len); crypto_digest_t *crypto_digest_dup(const crypto_digest_t *digest); +void crypto_digest_checkpoint(crypto_digest_checkpoint_t *checkpoint, + const crypto_digest_t *digest); +void crypto_digest_restore(crypto_digest_t *digest, + const crypto_digest_checkpoint_t *checkpoint); void crypto_digest_assign(crypto_digest_t *into, const crypto_digest_t *from); void crypto_hmac_sha256(char *hmac_out, diff --git a/src/common/log.c b/src/common/log.c index 9f4a8b2bc2..922e9dd38f 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -52,6 +52,13 @@ #define raw_assert(x) assert(x) // assert OK +/** Defining compile-time constants for Tor log levels (used by the Rust + * log wrapper at src/rust/tor_log) */ +const int LOG_WARN_ = LOG_WARN; +const int LOG_NOTICE_ = LOG_NOTICE; +const log_domain_mask_t LD_GENERAL_ = LD_GENERAL; +const log_domain_mask_t LD_NET_ = LD_NET; + /** Information for a single logfile; only used in log.c */ typedef struct logfile_t { struct logfile_t *next; /**< Next logfile_t in the linked list. */ @@ -225,6 +232,30 @@ log_set_application_name(const char *name) appname = name ? tor_strdup(name) : NULL; } +/** Return true if some of the running logs might be interested in a log + * message of the given severity in the given domains. If this function + * returns true, the log message might be ignored anyway, but if it returns + * false, it is definitely_ safe not to log the message. */ +int +log_message_is_interesting(int severity, log_domain_mask_t domain) +{ + (void) domain; + return (severity <= log_global_min_severity_); +} + +/** + * As tor_log, but takes an optional function name, and does not treat its + * <b>string</b> as a printf format. + * + * For use by Rust integration. + */ +void +tor_log_string(int severity, log_domain_mask_t domain, + const char *function, const char *string) +{ + log_fn_(severity, domain, function, "%s", string); +} + /** Log time granularity in milliseconds. */ static int log_time_granularity = 1; diff --git a/src/common/torlog.h b/src/common/torlog.h index cadfe3b879..ac632ff521 100644 --- a/src/common/torlog.h +++ b/src/common/torlog.h @@ -191,6 +191,10 @@ void log_fn_ratelim_(struct ratelim_t *ratelim, int severity, const char *format, ...) CHECK_PRINTF(5,6); +int log_message_is_interesting(int severity, log_domain_mask_t domain); +void tor_log_string(int severity, log_domain_mask_t domain, + const char *function, const char *string); + #if defined(__GNUC__) && __GNUC__ <= 3 /* These are the GCC varidaic macros, so that older versions of GCC don't @@ -248,6 +252,16 @@ void log_fn_ratelim_(struct ratelim_t *ratelim, int severity, args, ##__VA_ARGS__) #endif /* defined(__GNUC__) && __GNUC__ <= 3 */ +/** This defines log levels that are linked in the Rust log module, rather + * than re-defining these in both Rust and C. + * + * C_RUST_COUPLED src/rust/tor_log LogSeverity, LogDomain + */ +extern const int LOG_WARN_; +extern const int LOG_NOTICE_; +extern const log_domain_mask_t LD_NET_; +extern const log_domain_mask_t LD_GENERAL_; + #ifdef LOG_PRIVATE MOCK_DECL(STATIC void, logv, (int severity, log_domain_mask_t domain, const char *funcname, const char *suffix, const char *format, diff --git a/src/common/util.h b/src/common/util.h index 2ee0ea28cd..653c154aba 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -73,9 +73,9 @@ extern int dmalloc_free(const char *file, const int line, void *pnt, } \ STMT_END #else /* !(defined(USE_DMALLOC)) */ -/** Release memory allocated by tor_malloc, tor_realloc, tor_strdup, etc. - * Unlike the free() function, tor_free() will still work on NULL pointers, - * and it sets the pointer value to NULL after freeing it. +/** Release memory allocated by tor_malloc, tor_realloc, tor_strdup, + * etc. Unlike the free() function, the tor_free() macro sets the + * pointer value to NULL after freeing it. * * This is a macro. If you need a function pointer to release memory from * tor_malloc(), use tor_free_(). @@ -88,17 +88,13 @@ extern int dmalloc_free(const char *file, const int line, void *pnt, #ifdef __GNUC__ #define tor_free(p) STMT_BEGIN \ typeof(&(p)) tor_free__tmpvar = &(p); \ - if (PREDICT_LIKELY((*tor_free__tmpvar)!=NULL)) { \ - raw_free(*tor_free__tmpvar); \ - *tor_free__tmpvar=NULL; \ - } \ + raw_free(*tor_free__tmpvar); \ + *tor_free__tmpvar=NULL; \ STMT_END #else #define tor_free(p) STMT_BEGIN \ - if (PREDICT_LIKELY((p)!=NULL)) { \ - raw_free(p); \ - (p)=NULL; \ - } \ + raw_free(p); \ + (p)=NULL; \ STMT_END #endif #endif /* defined(USE_DMALLOC) */ |