blob: 658d82812305bf8250a177fa52d102a30fb5bb1d [file] [log] [blame]
Benoît Ganne9fb6d402019-04-15 15:28:21 +02001#ifndef _included_clib_sanitizer_h
2#define _included_clib_sanitizer_h
3
4#ifdef CLIB_SANITIZE_ADDR
5
6#include <sanitizer/asan_interface.h>
7#include <vppinfra/clib.h>
Benoît Ganned4721b22021-06-09 17:20:16 +02008#include <vppinfra/error_bootstrap.h>
9
10typedef struct
11{
12 size_t shadow_scale;
13 size_t shadow_offset;
14} clib_sanitizer_main_t;
15
16extern clib_sanitizer_main_t sanitizer_main;
Benoît Ganne9fb6d402019-04-15 15:28:21 +020017
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))
21
Benoît Ganned4721b22021-06-09 17:20:16 +020022#define CLIB_MEM_OVERFLOW_MAX 64
23
24static_always_inline void
25sanitizer_unpoison__ (u64 *restrict *shadow_ptr, size_t *shadow_len,
26 const void *ptr, size_t len)
27{
28 size_t scale, off;
29
30 if (PREDICT_FALSE (~0 == sanitizer_main.shadow_scale))
31 __asan_get_shadow_mapping (&sanitizer_main.shadow_scale,
32 &sanitizer_main.shadow_offset);
33
34 scale = sanitizer_main.shadow_scale;
35 off = sanitizer_main.shadow_offset;
36
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);
41}
42
43static_always_inline CLIB_NOSANITIZE_ADDR void
44sanitizer_unpoison_push__ (u64 *restrict shadow, const void *ptr, size_t len)
45{
46 u64 *restrict shadow_ptr;
47 size_t shadow_len;
48 int i;
49
50 sanitizer_unpoison__ (&shadow_ptr, &shadow_len, ptr, len);
51
52 /* save the shadow area */
53 for (i = 0; i < shadow_len; i++)
54 shadow[i] = shadow_ptr[i];
55
56 /* unpoison */
57 for (i = 0; i < shadow_len; i++)
58 shadow_ptr[i] = 0;
59}
60
61static_always_inline CLIB_NOSANITIZE_ADDR void
62sanitizer_unpoison_pop__ (const u64 *restrict shadow, const void *ptr,
63 size_t len)
64{
65 u64 *restrict shadow_ptr;
66 size_t shadow_len;
67 int i;
68
69 sanitizer_unpoison__ (&shadow_ptr, &shadow_len, ptr, len);
70
71 /* restore the shadow area */
72 for (i = 0; i < shadow_len; i++)
73 {
74 ASSERT (0 == shadow_ptr[i]);
75 shadow_ptr[i] = shadow[i];
76 }
77}
78
79#define CLIB_MEM_OVERFLOW(f, src, n) \
80 ({ \
81 typeof (f) clib_mem_overflow_ret__; \
82 const void *clib_mem_overflow_src__ = (src); \
83 size_t clib_mem_overflow_n__ = (n); \
84 u64 clib_mem_overflow_shadow__[CLIB_MEM_OVERFLOW_MAX]; \
85 sanitizer_unpoison_push__ (clib_mem_overflow_shadow__, \
86 clib_mem_overflow_src__, \
87 clib_mem_overflow_n__); \
88 clib_mem_overflow_ret__ = f; \
89 sanitizer_unpoison_pop__ (clib_mem_overflow_shadow__, \
90 clib_mem_overflow_src__, \
91 clib_mem_overflow_n__); \
92 clib_mem_overflow_ret__; \
93 })
Benoît Ganne9fb6d402019-04-15 15:28:21 +020094
95#define CLIB_MEM_OVERFLOW_LOAD(f, src) \
96 ({ \
97 typeof(src) clib_mem_overflow_load_src__ = (src); \
98 CLIB_MEM_OVERFLOW(f(clib_mem_overflow_load_src__), clib_mem_overflow_load_src__, sizeof(typeof(f(clib_mem_overflow_load_src__)))); \
99 })
100
101static_always_inline void
102CLIB_MEM_POISON_LEN (void *src, size_t oldlen, size_t newlen)
103{
104 if (oldlen > newlen)
105 CLIB_MEM_POISON (src + newlen, oldlen - newlen);
106 else if (newlen > oldlen)
107 CLIB_MEM_UNPOISON (src + oldlen, newlen - oldlen);
108}
109
110#else /* CLIB_SANITIZE_ADDR */
111
112#define CLIB_NOSANITIZE_ADDR
113#define CLIB_MEM_POISON(a, s) (void)(a)
114#define CLIB_MEM_UNPOISON(a, s) (void)(a)
115#define CLIB_MEM_OVERFLOW(a, b, c) a
116#define CLIB_MEM_OVERFLOW_LOAD(f, src) f(src)
117#define CLIB_MEM_POISON_LEN(a, b, c)
118
119#endif /* CLIB_SANITIZE_ADDR */
120
Benoît Ganne01a103b2020-07-09 14:23:51 +0200121/*
122 * clang tends to force alignment of all sections when compiling for address
123 * sanitizer. This confuse VPP plugin infra, prevent clang to do that
124 * On the contrary, GCC does not support this kind of attribute on sections
125 * sigh.
126 */
127#ifdef __clang__
128#define CLIB_NOSANITIZE_PLUGIN_REG_SECTION CLIB_NOSANITIZE_ADDR
129#else
130#define CLIB_NOSANITIZE_PLUGIN_REG_SECTION
131#endif
132
Benoît Ganne9fb6d402019-04-15 15:28:21 +0200133#endif /* _included_clib_sanitizer_h */
134
135/*
136 * fd.io coding-style-patch-verification: ON
137 *
138 * Local Variables:
139 * eval: (c-set-style "gnu")
140 * End:
141 */