aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/cc/compat_compiler.h31
-rw-r--r--src/lib/metrics/metrics_common.c13
-rw-r--r--src/lib/metrics/metrics_common.h3
-rw-r--r--src/lib/metrics/metrics_store.c21
-rw-r--r--src/lib/metrics/metrics_store.h1
-rw-r--r--src/lib/metrics/prometheus.c11
-rw-r--r--src/lib/metrics/prometheus.h2
-rw-r--r--src/lib/net/address.c22
-rw-r--r--src/lib/sandbox/sandbox.c130
-rw-r--r--src/lib/string/printf.c4
10 files changed, 207 insertions, 31 deletions
diff --git a/src/lib/cc/compat_compiler.h b/src/lib/cc/compat_compiler.h
index 50bfedffba..991b33d9e7 100644
--- a/src/lib/cc/compat_compiler.h
+++ b/src/lib/cc/compat_compiler.h
@@ -15,6 +15,15 @@
#include "orconfig.h"
#include <inttypes.h>
+#if defined(__MINGW32__) || defined(__MINGW64__)
+#define MINGW_ANY
+#endif
+
+#ifdef MINGW_ANY
+/* We need this for __MINGW_PRINTF_FORMAT, alas. */
+#include <stdio.h>
+#endif
+
#if defined(__has_feature)
# if __has_feature(address_sanitizer)
/* Some of the fancy glibc strcmp() macros include references to memory that
@@ -36,16 +45,30 @@
#error "It seems that you encode characters in something other than ASCII."
#endif
+/* Use the right magic attribute on mingw, which might be printf, gnu_printf,
+ * or ms_printf, depending on how we're set up to build.
+ */
+#ifdef __MINGW_PRINTF_FORMAT
+#define PRINTF_FORMAT_ATTR __MINGW_PRINTF_FORMAT
+#else
+#define PRINTF_FORMAT_ATTR printf
+#endif
+#ifdef __MINGW_SCANF_FORMAT
+#define SCANF_FORMAT_ATTR __MINGW_SCANF_FORMAT
+#else
+#define SCANF_FORMAT_ATTR scanf
+#endif
+
/* GCC can check printf and scanf types on arbitrary functions. */
#ifdef __GNUC__
#define CHECK_PRINTF(formatIdx, firstArg) \
- __attribute__ ((format(printf, formatIdx, firstArg)))
+ __attribute__ ((format(PRINTF_FORMAT_ATTR, formatIdx, firstArg)))
#else
#define CHECK_PRINTF(formatIdx, firstArg)
#endif /* defined(__GNUC__) */
#ifdef __GNUC__
#define CHECK_SCANF(formatIdx, firstArg) \
- __attribute__ ((format(scanf, formatIdx, firstArg)))
+ __attribute__ ((format(SCANF_FORMAT_ATTR, formatIdx, firstArg)))
#else
#define CHECK_SCANF(formatIdx, firstArg)
#endif /* defined(__GNUC__) */
@@ -191,10 +214,6 @@
#define OP_EQ ==
#define OP_NE !=
-#if defined(__MINGW32__) || defined(__MINGW64__)
-#define MINGW_ANY
-#endif
-
/** Macro: yield a pointer to the field at position <b>off</b> within the
* structure <b>st</b>. Example:
* <pre>
diff --git a/src/lib/metrics/metrics_common.c b/src/lib/metrics/metrics_common.c
index 5941a4d892..f3f7e22d88 100644
--- a/src/lib/metrics/metrics_common.c
+++ b/src/lib/metrics/metrics_common.c
@@ -11,6 +11,7 @@
#include "orconfig.h"
#include "lib/log/util_bug.h"
+#include "lib/string/printf.h"
#include "lib/metrics/metrics_common.h"
@@ -27,3 +28,15 @@ metrics_type_to_str(const metrics_type_t type)
tor_assert_unreached();
}
}
+
+/** Return a static buffer pointer that contains a formatted label on the form
+ * of key=value.
+ *
+ * Subsequent call to this function invalidates the previous buffer. */
+const char *
+metrics_format_label(const char *key, const char *value)
+{
+ static char buf[128];
+ tor_snprintf(buf, sizeof(buf), "%s=\"%s\"", key, value);
+ return buf;
+}
diff --git a/src/lib/metrics/metrics_common.h b/src/lib/metrics/metrics_common.h
index 59aa9c0e90..3644ad3d50 100644
--- a/src/lib/metrics/metrics_common.h
+++ b/src/lib/metrics/metrics_common.h
@@ -42,4 +42,7 @@ typedef struct metrics_gauge_t {
const char *metrics_type_to_str(const metrics_type_t type);
+/* Helpers. */
+const char *metrics_format_label(const char *key, const char *value);
+
#endif /* !defined(TOR_LIB_METRICS_METRICS_COMMON_H) */
diff --git a/src/lib/metrics/metrics_store.c b/src/lib/metrics/metrics_store.c
index 4cab5245f3..33b1780438 100644
--- a/src/lib/metrics/metrics_store.c
+++ b/src/lib/metrics/metrics_store.c
@@ -34,7 +34,8 @@ struct metrics_store_t {
};
/** Function pointer to the format function of a specific driver. */
-typedef void (fmt_driver_fn_t)(const metrics_store_entry_t *, buf_t *);
+typedef void (fmt_driver_fn_t)(const metrics_store_entry_t *, buf_t *,
+ bool no_comment);
/** Helper: Free a single entry in a metrics_store_t taking a void pointer
* parameter. */
@@ -47,6 +48,8 @@ metrics_store_free_void(void *p)
smartlist_free(list);
}
+#include <stdio.h>
+
/** Put the given store output in the buffer data and use the format function
* given in fmt to get it for each entry. */
static void
@@ -57,8 +60,11 @@ get_output(const metrics_store_t *store, buf_t *data, fmt_driver_fn_t fmt)
tor_assert(fmt);
STRMAP_FOREACH(store->entries, key, const smartlist_t *, entries) {
+ /* Indicate that we've formatted the coment already for the entries. */
+ bool comment_formatted = false;
SMARTLIST_FOREACH_BEGIN(entries, const metrics_store_entry_t *, entry) {
- fmt(entry, data);
+ fmt(entry, data, comment_formatted);
+ comment_formatted = true;
} SMARTLIST_FOREACH_END(entry);
} STRMAP_FOREACH_END;
}
@@ -138,3 +144,14 @@ metrics_store_get_output(const metrics_format_t fmt,
// LCOV_EXCL_STOP
}
}
+
+/** Reset a store as in free its content. */
+void
+metrics_store_reset(metrics_store_t *store)
+{
+ if (store == NULL) {
+ return;
+ }
+ strmap_free(store->entries, metrics_store_free_void);
+ store->entries = strmap_new();
+}
diff --git a/src/lib/metrics/metrics_store.h b/src/lib/metrics/metrics_store.h
index 42bc56e8fd..d85f484bd6 100644
--- a/src/lib/metrics/metrics_store.h
+++ b/src/lib/metrics/metrics_store.h
@@ -28,6 +28,7 @@ metrics_store_t *metrics_store_new(void);
metrics_store_entry_t *metrics_store_add(metrics_store_t *store,
metrics_type_t type,
const char *name, const char *help);
+void metrics_store_reset(metrics_store_t *store);
/* Accessors. */
smartlist_t *metrics_store_get_all(const metrics_store_t *store,
diff --git a/src/lib/metrics/prometheus.c b/src/lib/metrics/prometheus.c
index 65241ed6c1..aac23ac92e 100644
--- a/src/lib/metrics/prometheus.c
+++ b/src/lib/metrics/prometheus.c
@@ -42,14 +42,17 @@ format_labels(smartlist_t *labels)
/** Format the given entry in to the buffer data. */
void
-prometheus_format_store_entry(const metrics_store_entry_t *entry, buf_t *data)
+prometheus_format_store_entry(const metrics_store_entry_t *entry, buf_t *data,
+ bool no_comment)
{
tor_assert(entry);
tor_assert(data);
- buf_add_printf(data, "# HELP %s %s\n", entry->name, entry->help);
- buf_add_printf(data, "# TYPE %s %s\n", entry->name,
- metrics_type_to_str(entry->type));
+ if (!no_comment) {
+ buf_add_printf(data, "# HELP %s %s\n", entry->name, entry->help);
+ buf_add_printf(data, "# TYPE %s %s\n", entry->name,
+ metrics_type_to_str(entry->type));
+ }
buf_add_printf(data, "%s%s %" PRIi64 "\n", entry->name,
format_labels(entry->labels),
metrics_store_entry_get_value(entry));
diff --git a/src/lib/metrics/prometheus.h b/src/lib/metrics/prometheus.h
index 19770e7911..faa7681daa 100644
--- a/src/lib/metrics/prometheus.h
+++ b/src/lib/metrics/prometheus.h
@@ -13,6 +13,6 @@
#include "lib/metrics/metrics_store_entry.h"
void prometheus_format_store_entry(const metrics_store_entry_t *entry,
- buf_t *data);
+ buf_t *data, bool no_comment);
#endif /* !defined(TOR_LIB_METRICS_PROMETHEUS_H) */
diff --git a/src/lib/net/address.c b/src/lib/net/address.c
index 26b155bc4c..085eb8c458 100644
--- a/src/lib/net/address.c
+++ b/src/lib/net/address.c
@@ -2005,20 +2005,15 @@ parse_port_range(const char *port, uint16_t *port_min_out,
char *endptr = NULL;
port_min = (int)tor_parse_long(port, 10, 0, 65535, &ok, &endptr);
if (!ok) {
- log_warn(LD_GENERAL,
- "Malformed port %s on address range; rejecting.",
- escaped(port));
- return -1;
- } else if (endptr && *endptr == '-') {
+ goto malformed_port;
+ } else if (endptr && *endptr != '\0') {
+ if (*endptr != '-')
+ goto malformed_port;
port = endptr+1;
endptr = NULL;
port_max = (int)tor_parse_long(port, 10, 1, 65535, &ok, &endptr);
- if (!ok) {
- log_warn(LD_GENERAL,
- "Malformed port %s on address range; rejecting.",
- escaped(port));
- return -1;
- }
+ if (!ok)
+ goto malformed_port;
} else {
port_max = port_min;
}
@@ -2037,6 +2032,11 @@ parse_port_range(const char *port, uint16_t *port_min_out,
*port_max_out = (uint16_t) port_max;
return 0;
+ malformed_port:
+ log_warn(LD_GENERAL,
+ "Malformed port %s on address range; rejecting.",
+ escaped(port));
+ return -1;
}
/** Given a host-order <b>addr</b>, call tor_inet_ntop() on it
diff --git a/src/lib/sandbox/sandbox.c b/src/lib/sandbox/sandbox.c
index 02222e5a1c..a15f99ad76 100644
--- a/src/lib/sandbox/sandbox.c
+++ b/src/lib/sandbox/sandbox.c
@@ -58,6 +58,10 @@
#include <linux/futex.h>
#include <sys/file.h>
+#ifdef ENABLE_FRAGILE_HARDENING
+#include <sys/ptrace.h>
+#endif
+
#include <stdarg.h>
#include <seccomp.h>
#include <signal.h>
@@ -148,7 +152,11 @@ static sandbox_cfg_t *filter_dynamic = NULL;
static int filter_nopar_gen[] = {
SCMP_SYS(access),
SCMP_SYS(brk),
+#ifdef __NR_clock_gettime64
+ SCMP_SYS(clock_gettime64),
+#else
SCMP_SYS(clock_gettime),
+#endif
SCMP_SYS(close),
SCMP_SYS(clone),
SCMP_SYS(dup),
@@ -191,6 +199,9 @@ static int filter_nopar_gen[] = {
SCMP_SYS(getgid32),
#endif
SCMP_SYS(getpid),
+#ifdef ENABLE_FRAGILE_HARDENING
+ SCMP_SYS(getppid),
+#endif
#ifdef __NR_getrlimit
SCMP_SYS(getrlimit),
#endif
@@ -241,6 +252,9 @@ static int filter_nopar_gen[] = {
SCMP_SYS(sigreturn),
#endif
SCMP_SYS(stat),
+#if defined(__i386__) && defined(__NR_statx)
+ SCMP_SYS(statx),
+#endif
SCMP_SYS(uname),
SCMP_SYS(wait4),
SCMP_SYS(write),
@@ -339,6 +353,7 @@ sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return rc;
}
+#ifdef __NR_time
/**
* Function responsible for setting up the time syscall for
* the seccomp filter sandbox.
@@ -347,13 +362,11 @@ static int
sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
(void) filter;
-#ifdef __NR_time
+
return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time),
SCMP_CMP(0, SCMP_CMP_EQ, 0));
-#else
- return 0;
-#endif /* defined(__NR_time) */
}
+#endif /* defined(__NR_time) */
/**
* Function responsible for setting up the accept4 syscall for
@@ -532,6 +545,24 @@ sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
int use_openat = libc_uses_openat_for_open();
+#ifdef ENABLE_FRAGILE_HARDENING
+ /* AddressSanitizer uses the "open" syscall to access information about the
+ * running process via the filesystem, so that call must be allowed without
+ * restriction or the sanitizer will be unable to execute normally when the
+ * process terminates. */
+ rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open));
+ if (rc != 0) {
+ log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
+ "libseccomp error %d", rc);
+ return rc;
+ }
+
+ /* If glibc also uses only the "open" syscall to open files on this system
+ * there is no need to consider any additional rules. */
+ if (!use_openat)
+ return 0;
+#endif
+
// for each dynamic parameter filters
for (elem = filter; elem != NULL; elem = elem->next) {
smp_param_t *param = elem->param;
@@ -575,6 +606,32 @@ sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#ifdef __i386__
+static int
+sb_chown32(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(chown32)) {
+ rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown32),
+ SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
+ if (rc != 0) {
+ log_err(LD_BUG,"(Sandbox) failed to add chown32 syscall, received "
+ "libseccomp error %d", rc);
+ return rc;
+ }
+ }
+ }
+
+ return 0;
+}
+#else
static int
sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
@@ -599,6 +656,7 @@ sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#endif /* defined(__i386__) */
/**
* Function responsible for setting up the rename syscall for
@@ -687,6 +745,34 @@ sb_opendir(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return 0;
}
+#ifdef ENABLE_FRAGILE_HARDENING
+/**
+ * Function responsible for setting up the ptrace syscall for
+ * the seccomp filter sandbox.
+ */
+static int
+sb_ptrace(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
+{
+ int rc;
+ pid_t pid = getpid();
+ (void) filter;
+
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
+ SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_ATTACH),
+ SCMP_CMP(1, SCMP_CMP_EQ, pid));
+ if (rc)
+ return rc;
+
+ rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
+ SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_GETREGS),
+ SCMP_CMP(1, SCMP_CMP_EQ, pid));
+ if (rc)
+ return rc;
+
+ return 0;
+}
+#endif
+
/**
* Function responsible for setting up the socket syscall for
* the seccomp filter sandbox.
@@ -1009,6 +1095,18 @@ sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
int rc = 0;
(void) filter;
+#ifdef ENABLE_FRAGILE_HARDENING
+ rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
+ SCMP_CMP(0, SCMP_CMP_EQ, PR_GET_DUMPABLE));
+ if (rc)
+ return rc;
+
+ rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
+ SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_PTRACER));
+ if (rc)
+ return rc;
+#endif
+
rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE));
if (rc)
@@ -1053,6 +1151,13 @@ sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
int rc = 0;
(void) filter;
+#ifdef ENABLE_FRAGILE_HARDENING
+ rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
+ SCMP_CMP(0, SCMP_CMP_EQ, SIG_BLOCK));
+ if (rc)
+ return rc;
+#endif
+
rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK));
if (rc)
@@ -1192,16 +1297,25 @@ sb_kill(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
static sandbox_filter_func_t filter_func[] = {
sb_rt_sigaction,
sb_rt_sigprocmask,
+#ifdef __NR_time
sb_time,
+#endif
sb_accept4,
#ifdef __NR_mmap2
sb_mmap2,
#endif
+#ifdef __i386__
+ sb_chown32,
+#else
sb_chown,
+#endif
sb_chmod,
sb_open,
sb_openat,
sb_opendir,
+#ifdef ENABLE_FRAGILE_HARDENING
+ sb_ptrace,
+#endif
sb_rename,
#ifdef __NR_fcntl64
sb_fcntl64,
@@ -1468,6 +1582,12 @@ new_element(int syscall, char *value)
return new_element2(syscall, value, NULL);
}
+#ifdef __i386__
+#define SCMP_chown SCMP_SYS(chown32)
+#else
+#define SCMP_chown SCMP_SYS(chown)
+#endif
+
#ifdef __NR_stat64
#define SCMP_stat SCMP_SYS(stat64)
#else
@@ -1518,7 +1638,7 @@ sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file)
{
sandbox_cfg_t *elem = NULL;
- elem = new_element(SCMP_SYS(chown), file);
+ elem = new_element(SCMP_chown, file);
elem->next = *cfg;
*cfg = elem;
diff --git a/src/lib/string/printf.c b/src/lib/string/printf.c
index 62758093a7..bd35b76d1b 100644
--- a/src/lib/string/printf.c
+++ b/src/lib/string/printf.c
@@ -8,9 +8,9 @@
* \brief Compatibility wrappers around snprintf and its friends
**/
+#include "lib/cc/torint.h"
#include "lib/string/printf.h"
#include "lib/err/torerr.h"
-#include "lib/cc/torint.h"
#include "lib/malloc/malloc.h"
#include <stdlib.h>
@@ -45,7 +45,7 @@ tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
return -1; /* no place for the NUL */
if (size > SIZE_T_CEILING)
return -1;
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(HAVE_VSNPRINTF)
r = _vsnprintf(str, size, format, args);
#else
r = vsnprintf(str, size, format, args);