Browse Source

Merge branch 'disable_memory_sentinels_squashed'

Nick Mathewson 7 years ago
parent
commit
c0aa7ac5ac
5 changed files with 121 additions and 1 deletions
  1. 7 0
      changes/bug21439
  2. 7 0
      configure.ac
  3. 91 0
      src/common/memarea.c
  4. 9 1
      src/or/buffers.c
  5. 7 0
      src/test/test_util.c

+ 7 - 0
changes/bug21439

@@ -0,0 +1,7 @@
+  o Minor features (testing):
+    - Add a "--disable-memory-sentinels" feature to help with fuzzing.
+      When Tor is compiled with this option, we disable a number of
+      redundant memory-safety failsafes that are intended to stop
+      bugs from becoming security issues. This makes it easier to hunt
+      for bugs that would be security issues without the failsafes
+      turned on. Closes ticket 21439.

+ 7 - 0
configure.ac

@@ -53,6 +53,8 @@ AC_ARG_ENABLE(libfuzzer,
    AS_HELP_STRING(--enable-libfuzzer, [build extra fuzzers based on 'libfuzzer']))
 AC_ARG_ENABLE(oss-fuzz,
    AS_HELP_STRING(--enable-oss-fuzz, [build extra fuzzers based on 'oss-fuzz' environment]))
+AC_ARG_ENABLE(memory-sentinels,
+   AS_HELP_STRING(--disable-memory-sentinels, [disable code that tries to prevent some kinds of memory access bugs. For fuzzing only.]))
 
 if test "x$enable_coverage" != "xyes" -a "x$enable_asserts_in_tests" = "xno" ; then
     AC_MSG_ERROR([Can't disable assertions outside of coverage build])
@@ -76,6 +78,11 @@ if test "$enable_system_torrc" = "no"; then
             [Defined if we're not going to look for a torrc in SYSCONF])
 fi
 
+if test "$enable_memory_sentinels" = "no"; then
+  AC_DEFINE(DISABLE_MEMORY_SENTINELS, 1,
+           [Defined if we're turning off memory safety code to look for bugs])
+fi
+
 AM_CONDITIONAL(USE_OPENBSD_MALLOC, test "x$enable_openbsd_malloc" = "xyes")
 
 AC_ARG_ENABLE(asciidoc,

+ 91 - 0
src/common/memarea.c

@@ -12,6 +12,9 @@
 #include "util.h"
 #include "compat.h"
 #include "torlog.h"
+#include "container.h"
+
+#ifndef DISABLE_MEMORY_SENTINELS
 
 /** If true, we try to detect any attempts to write beyond the length of a
  * memarea. */
@@ -304,3 +307,91 @@ memarea_assert_ok(memarea_t *area)
   }
 }
 
+#else
+
+struct memarea_t {
+  smartlist_t *pieces;
+};
+
+memarea_t *
+memarea_new(void)
+{
+  memarea_t *ma = tor_malloc_zero(sizeof(memarea_t));
+  ma->pieces = smartlist_new();
+  return ma;
+}
+void
+memarea_drop_all(memarea_t *area)
+{
+  memarea_clear(area);
+  smartlist_free(area->pieces);
+  tor_free(area);
+}
+void
+memarea_clear(memarea_t *area)
+{
+  SMARTLIST_FOREACH(area->pieces, void *, p, tor_free_(p));
+  smartlist_clear(area->pieces);
+}
+int
+memarea_owns_ptr(const memarea_t *area, const void *ptr)
+{
+  SMARTLIST_FOREACH(area->pieces, const void *, p, if (ptr == p) return 1;);
+  return 0;
+}
+
+void *
+memarea_alloc(memarea_t *area, size_t sz)
+{
+  void *result = tor_malloc(sz);
+  smartlist_add(area->pieces, result);
+  return result;
+}
+
+void *
+memarea_alloc_zero(memarea_t *area, size_t sz)
+{
+  void *result = tor_malloc_zero(sz);
+  smartlist_add(area->pieces, result);
+  return result;
+}
+void *
+memarea_memdup(memarea_t *area, const void *s, size_t n)
+{
+  void *r = memarea_alloc(area, n);
+  memcpy(r, s, n);
+  return r;
+}
+char *
+memarea_strdup(memarea_t *area, const char *s)
+{
+  size_t n = strlen(s);
+  char *r = memarea_alloc(area, n+1);
+  memcpy(r, s, n);
+  r[n] = 0;
+  return r;
+}
+char *
+memarea_strndup(memarea_t *area, const char *s, size_t n)
+{
+  size_t ln = strnlen(s, n);
+  char *r = memarea_alloc(area, ln+1);
+  memcpy(r, s, ln);
+  r[ln] = 0;
+  return r;
+}
+void
+memarea_get_stats(memarea_t *area,
+                  size_t *allocated_out, size_t *used_out)
+{
+  (void)area;
+  *allocated_out = *used_out = 128;
+}
+void
+memarea_assert_ok(memarea_t *area)
+{
+  (void)area;
+}
+
+#endif
+

+ 9 - 1
src/or/buffers.c

@@ -83,7 +83,11 @@ static int parse_socks_client(const uint8_t *data, size_t datalen,
 #define CHUNK_HEADER_LEN STRUCT_OFFSET(chunk_t, mem[0])
 
 /* We leave this many NUL bytes at the end of the buffer. */
+#ifdef DISABLE_MEMORY_SENTINELS
+#define SENTINEL_LEN 0
+#else
 #define SENTINEL_LEN 4
+#endif
 
 /* Header size plus NUL bytes at the end */
 #define CHUNK_OVERHEAD (CHUNK_HEADER_LEN + SENTINEL_LEN)
@@ -97,18 +101,22 @@ static int parse_socks_client(const uint8_t *data, size_t datalen,
 
 #define DEBUG_SENTINEL
 
-#ifdef DEBUG_SENTINEL
+#if defined(DEBUG_SENTINEL) && !defined(DISABLE_MEMORY_SENTINELS)
 #define DBG_S(s) s
 #else
 #define DBG_S(s) (void)0
 #endif
 
+#ifdef DISABLE_MEMORY_SENTINELS
+#define CHUNK_SET_SENTINEL(chunk, alloclen) STMT_NIL
+#else
 #define CHUNK_SET_SENTINEL(chunk, alloclen) do {                        \
     uint8_t *a = (uint8_t*) &(chunk)->mem[(chunk)->memlen];             \
     DBG_S(uint8_t *b = &((uint8_t*)(chunk))[(alloclen)-SENTINEL_LEN]);  \
     DBG_S(tor_assert(a == b));                                          \
     memset(a,0,SENTINEL_LEN);                                           \
   } while (0)
+#endif
 
 /** Return the next character in <b>chunk</b> onto which data can be appended.
  * If the chunk is full, this might be off the end of chunk->mem. */

+ 7 - 0
src/test/test_util.c

@@ -3340,6 +3340,13 @@ test_util_memarea(void *arg)
   void *malloced_ptr = NULL;
   int i;
 
+#ifdef DISABLE_MEMORY_SENTINELS
+  /* If memory sentinels are disabled, this whole module is just an alias for
+     malloc(), which is free to lay out memory most any way it wants. */
+  if (1)
+    tt_skip();
+#endif
+
   (void)arg;
   tt_assert(area);