summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/address.c18
-rw-r--r--src/common/buffers.h1
-rw-r--r--src/common/compat.c46
-rw-r--r--src/common/compat.h6
-rw-r--r--src/common/compat_winthreads.c1
-rw-r--r--src/common/compress.c10
-rw-r--r--src/common/compress.h1
-rw-r--r--src/common/compress_zstd.c112
-rw-r--r--src/common/compress_zstd.h7
-rw-r--r--src/common/crypto.c24
-rw-r--r--src/common/crypto.h11
-rw-r--r--src/common/log.c31
-rw-r--r--src/common/torlog.h14
-rw-r--r--src/common/util.h18
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) */