diff options
Diffstat (limited to 'src/vppinfra/sanitizer.h')
-rw-r--r-- | src/vppinfra/sanitizer.h | 95 |
1 files changed, 81 insertions, 14 deletions
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) \ ({ \ |