1 #ifndef _included_clib_sanitizer_h
2 #define _included_clib_sanitizer_h
4 #ifdef CLIB_SANITIZE_ADDR
6 #include <sanitizer/asan_interface.h>
7 #include <vppinfra/clib.h>
8 #include <vppinfra/error_bootstrap.h>
14 } clib_sanitizer_main_t;
16 extern clib_sanitizer_main_t sanitizer_main;
18 #define CLIB_NOSANITIZE_ADDR __attribute__((no_sanitize_address))
19 #define CLIB_MEM_POISON(a, s) ASAN_POISON_MEMORY_REGION((a), (s))
20 #define CLIB_MEM_UNPOISON(a, s) ASAN_UNPOISON_MEMORY_REGION((a), (s))
22 #define CLIB_MEM_OVERFLOW_MAX 64
24 static_always_inline void
25 sanitizer_unpoison__ (u64 *restrict *shadow_ptr, size_t *shadow_len,
26 const void *ptr, size_t len)
30 if (PREDICT_FALSE (~0 == sanitizer_main.shadow_scale))
31 __asan_get_shadow_mapping (&sanitizer_main.shadow_scale,
32 &sanitizer_main.shadow_offset);
34 scale = sanitizer_main.shadow_scale;
35 off = sanitizer_main.shadow_offset;
37 /* compute the shadow address and length */
38 *shadow_len = len >> scale;
39 ASSERT (*shadow_len <= CLIB_MEM_OVERFLOW_MAX);
40 *shadow_ptr = (void *) (((clib_address_t) ptr >> scale) + off);
43 static_always_inline CLIB_NOSANITIZE_ADDR void
44 sanitizer_unpoison_push__ (u64 *restrict shadow, const void *ptr, size_t len)
46 u64 *restrict shadow_ptr;
50 sanitizer_unpoison__ (&shadow_ptr, &shadow_len, ptr, len);
52 /* save the shadow area */
53 for (i = 0; i < shadow_len; i++)
54 shadow[i] = shadow_ptr[i];
57 for (i = 0; i < shadow_len; i++)
61 static_always_inline CLIB_NOSANITIZE_ADDR void
62 sanitizer_unpoison_pop__ (const u64 *restrict shadow, const void *ptr,
65 u64 *restrict shadow_ptr;
69 sanitizer_unpoison__ (&shadow_ptr, &shadow_len, ptr, len);
71 /* restore the shadow area */
72 for (i = 0; i < shadow_len; i++)
74 ASSERT (0 == shadow_ptr[i]);
75 shadow_ptr[i] = shadow[i];
79 #define CLIB_MEM_OVERFLOW_PUSH(src, n) \
82 const void *clib_mem_overflow_src__ = (src); \
83 size_t clib_mem_overflow_n__ = (n); \
84 u64 clib_mem_overflow_shadow__; \
85 sanitizer_unpoison_push__ (&clib_mem_overflow_shadow__, \
86 clib_mem_overflow_src__, \
87 clib_mem_overflow_n__)
89 #define CLIB_MEM_OVERFLOW_POP() \
90 sanitizer_unpoison_pop__ (&clib_mem_overflow_shadow__, \
91 clib_mem_overflow_src__, clib_mem_overflow_n__); \
95 #define CLIB_MEM_OVERFLOW_LOAD(src) \
97 typeof (*(src)) *clib_mem_overflow_load_src__ = (src), \
98 clib_mem_overflow_load_ret__; \
99 CLIB_MEM_OVERFLOW_PUSH (clib_mem_overflow_load_src__, \
100 sizeof (*clib_mem_overflow_load_src__)); \
101 clib_mem_overflow_load_ret__ = *clib_mem_overflow_load_src__; \
102 CLIB_MEM_OVERFLOW_POP (); \
103 clib_mem_overflow_load_ret__; \
106 static_always_inline void
107 CLIB_MEM_POISON_LEN (void *src, size_t oldlen, size_t newlen)
110 CLIB_MEM_POISON (src + newlen, oldlen - newlen);
111 else if (newlen > oldlen)
112 CLIB_MEM_UNPOISON (src + oldlen, newlen - oldlen);
115 #else /* CLIB_SANITIZE_ADDR */
117 #define CLIB_NOSANITIZE_ADDR
118 #define CLIB_MEM_POISON(a, s) (void)(a)
119 #define CLIB_MEM_UNPOISON(a, s) (void)(a)
120 #define CLIB_MEM_OVERFLOW_PUSH(a, b) (void) (a)
121 #define CLIB_MEM_OVERFLOW_POP()
122 #define CLIB_MEM_OVERFLOW_LOAD(src) (*(src))
123 #define CLIB_MEM_POISON_LEN(a, b, c)
125 #endif /* CLIB_SANITIZE_ADDR */
128 * clang tends to force alignment of all sections when compiling for address
129 * sanitizer. This confuse VPP plugin infra, prevent clang to do that
130 * On the contrary, GCC does not support this kind of attribute on sections
134 #define CLIB_NOSANITIZE_PLUGIN_REG_SECTION CLIB_NOSANITIZE_ADDR
136 #define CLIB_NOSANITIZE_PLUGIN_REG_SECTION
139 #endif /* _included_clib_sanitizer_h */
142 * fd.io coding-style-patch-verification: ON
145 * eval: (c-set-style "gnu")