2019-04-15 15:28:21 +02:00
|
|
|
#ifndef _included_clib_sanitizer_h
|
|
|
|
|
#define _included_clib_sanitizer_h
|
|
|
|
|
|
|
|
|
|
#ifdef CLIB_SANITIZE_ADDR
|
|
|
|
|
|
|
|
|
|
#include <sanitizer/asan_interface.h>
|
|
|
|
|
#include <vppinfra/clib.h>
|
2021-06-09 17:20:16 +02:00
|
|
|
#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;
|
2019-04-15 15:28:21 +02:00
|
|
|
|
|
|
|
|
#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))
|
|
|
|
|
|
2021-06-09 17:20:16 +02:00
|
|
|
#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__; \
|
|
|
|
|
})
|
2019-04-15 15:28:21 +02:00
|
|
|
|
|
|
|
|
#define CLIB_MEM_OVERFLOW_LOAD(f, src) \
|
|
|
|
|
({ \
|
|
|
|
|
typeof(src) clib_mem_overflow_load_src__ = (src); \
|
|
|
|
|
CLIB_MEM_OVERFLOW(f(clib_mem_overflow_load_src__), clib_mem_overflow_load_src__, sizeof(typeof(f(clib_mem_overflow_load_src__)))); \
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
static_always_inline void
|
|
|
|
|
CLIB_MEM_POISON_LEN (void *src, size_t oldlen, size_t newlen)
|
|
|
|
|
{
|
|
|
|
|
if (oldlen > newlen)
|
|
|
|
|
CLIB_MEM_POISON (src + newlen, oldlen - newlen);
|
|
|
|
|
else if (newlen > oldlen)
|
|
|
|
|
CLIB_MEM_UNPOISON (src + oldlen, newlen - oldlen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else /* CLIB_SANITIZE_ADDR */
|
|
|
|
|
|
|
|
|
|
#define CLIB_NOSANITIZE_ADDR
|
|
|
|
|
#define CLIB_MEM_POISON(a, s) (void)(a)
|
|
|
|
|
#define CLIB_MEM_UNPOISON(a, s) (void)(a)
|
|
|
|
|
#define CLIB_MEM_OVERFLOW(a, b, c) a
|
|
|
|
|
#define CLIB_MEM_OVERFLOW_LOAD(f, src) f(src)
|
|
|
|
|
#define CLIB_MEM_POISON_LEN(a, b, c)
|
|
|
|
|
|
|
|
|
|
#endif /* CLIB_SANITIZE_ADDR */
|
|
|
|
|
|
2020-07-09 14:23:51 +02:00
|
|
|
/*
|
|
|
|
|
* clang tends to force alignment of all sections when compiling for address
|
|
|
|
|
* sanitizer. This confuse VPP plugin infra, prevent clang to do that
|
|
|
|
|
* On the contrary, GCC does not support this kind of attribute on sections
|
|
|
|
|
* sigh.
|
|
|
|
|
*/
|
|
|
|
|
#ifdef __clang__
|
|
|
|
|
#define CLIB_NOSANITIZE_PLUGIN_REG_SECTION CLIB_NOSANITIZE_ADDR
|
|
|
|
|
#else
|
|
|
|
|
#define CLIB_NOSANITIZE_PLUGIN_REG_SECTION
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-04-15 15:28:21 +02:00
|
|
|
#endif /* _included_clib_sanitizer_h */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* fd.io coding-style-patch-verification: ON
|
|
|
|
|
*
|
|
|
|
|
* Local Variables:
|
|
|
|
|
* eval: (c-set-style "gnu")
|
|
|
|
|
* End:
|
|
|
|
|
*/
|