summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vppinfra/CMakeLists.txt1
-rw-r--r--src/vppinfra/sanitizer.c7
-rw-r--r--src/vppinfra/sanitizer.h95
3 files changed, 89 insertions, 14 deletions
diff --git a/src/vppinfra/CMakeLists.txt b/src/vppinfra/CMakeLists.txt
index 6da1fa2a0a1..64420b96676 100644
--- a/src/vppinfra/CMakeLists.txt
+++ b/src/vppinfra/CMakeLists.txt
@@ -77,6 +77,7 @@ set(VPPINFRA_SRCS
random.c
random_isaac.c
rbtree.c
+ sanitizer.c
serialize.c
socket.c
std-formats.c
diff --git a/src/vppinfra/sanitizer.c b/src/vppinfra/sanitizer.c
new file mode 100644
index 00000000000..fab1cdca136
--- /dev/null
+++ b/src/vppinfra/sanitizer.c
@@ -0,0 +1,7 @@
+#ifdef CLIB_SANITIZE_ADDR
+
+#include <vppinfra/sanitizer.h>
+
+__clib_export clib_sanitizer_main_t sanitizer_main = { .shadow_scale = ~0 };
+
+#endif /* CLIB_SANITIZE_ADDR */
diff --git a/src/vppinfra/sanitizer.h b/src/vppinfra/sanitizer.h
index db4daea978d..658d8281230 100644
--- a/src/vppinfra/sanitizer.h
+++ b/src/vppinfra/sanitizer.h
@@ -5,25 +5,92 @@
#include <sanitizer/asan_interface.h>
#include <vppinfra/clib.h>
+#include <vppinfra/error_bootstrap.h>
+
+typedef struct
+{
+ size_t shadow_scale;
+ size_t shadow_offset;
+} clib_sanitizer_main_t;
+
+extern clib_sanitizer_main_t sanitizer_main;
#define CLIB_NOSANITIZE_ADDR __attribute__((no_sanitize_address))
#define CLIB_MEM_POISON(a, s) ASAN_POISON_MEMORY_REGION((a), (s))
#define CLIB_MEM_UNPOISON(a, s) ASAN_UNPOISON_MEMORY_REGION((a), (s))
-#define CLIB_MEM_OVERFLOW(f, src, n) \
- ({ \
- typeof (f) clib_mem_overflow_ret__; \
- const void *clib_mem_overflow_src__ = (src); \
- size_t clib_mem_overflow_n__ = (n); \
- const void *clib_mem_overflow_start__ = __asan_region_is_poisoned((void *)clib_mem_overflow_src__, clib_mem_overflow_n__); \
- clib_mem_overflow_n__ -= (size_t)(clib_mem_overflow_start__ - clib_mem_overflow_src__); \
- if (clib_mem_overflow_start__) \
- CLIB_MEM_UNPOISON(clib_mem_overflow_start__, clib_mem_overflow_n__); \
- clib_mem_overflow_ret__ = f; \
- if (clib_mem_overflow_start__) \
- CLIB_MEM_POISON(clib_mem_overflow_start__, clib_mem_overflow_n__); \
- clib_mem_overflow_ret__; \
- })
+#define CLIB_MEM_OVERFLOW_MAX 64
+
+static_always_inline void
+sanitizer_unpoison__ (u64 *restrict *shadow_ptr, size_t *shadow_len,
+ const void *ptr, size_t len)
+{
+ size_t scale, off;
+
+ if (PREDICT_FALSE (~0 == sanitizer_main.shadow_scale))
+ __asan_get_shadow_mapping (&sanitizer_main.shadow_scale,
+ &sanitizer_main.shadow_offset);
+
+ scale = sanitizer_main.shadow_scale;
+ off = sanitizer_main.shadow_offset;
+
+ /* compute the shadow address and length */
+ *shadow_len = len >> scale;
+ ASSERT (*shadow_len <= CLIB_MEM_OVERFLOW_MAX);
+ *shadow_ptr = (void *) (((clib_address_t) ptr >> scale) + off);
+}
+
+static_always_inline CLIB_NOSANITIZE_ADDR void
+sanitizer_unpoison_push__ (u64 *restrict shadow, const void *ptr, size_t len)
+{
+ u64 *restrict shadow_ptr;
+ size_t shadow_len;
+ int i;
+
+ sanitizer_unpoison__ (&shadow_ptr, &shadow_len, ptr, len);
+
+ /* save the shadow area */
+ for (i = 0; i < shadow_len; i++)
+ shadow[i] = shadow_ptr[i];
+
+ /* unpoison */
+ for (i = 0; i < shadow_len; i++)
+ shadow_ptr[i] = 0;
+}
+
+static_always_inline CLIB_NOSANITIZE_ADDR void
+sanitizer_unpoison_pop__ (const u64 *restrict shadow, const void *ptr,
+ size_t len)
+{
+ u64 *restrict shadow_ptr;
+ size_t shadow_len;
+ int i;
+
+ sanitizer_unpoison__ (&shadow_ptr, &shadow_len, ptr, len);
+
+ /* restore the shadow area */
+ for (i = 0; i < shadow_len; i++)
+ {
+ ASSERT (0 == shadow_ptr[i]);
+ shadow_ptr[i] = shadow[i];
+ }
+}
+
+#define CLIB_MEM_OVERFLOW(f, src, n) \
+ ({ \
+ typeof (f) clib_mem_overflow_ret__; \
+ const void *clib_mem_overflow_src__ = (src); \
+ size_t clib_mem_overflow_n__ = (n); \
+ u64 clib_mem_overflow_shadow__[CLIB_MEM_OVERFLOW_MAX]; \
+ sanitizer_unpoison_push__ (clib_mem_overflow_shadow__, \
+ clib_mem_overflow_src__, \
+ clib_mem_overflow_n__); \
+ clib_mem_overflow_ret__ = f; \
+ sanitizer_unpoison_pop__ (clib_mem_overflow_shadow__, \
+ clib_mem_overflow_src__, \
+ clib_mem_overflow_n__); \
+ clib_mem_overflow_ret__; \
+ })
#define CLIB_MEM_OVERFLOW_LOAD(f, src) \
({ \