File: | compiler-rt/lib/dfsan/../dfsan/dfsan_origin.h |
Warning: | line 101, column 26 The result of the left shift is undefined because the left operand is negative |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- dfsan.cpp ---------------------------------------------------------===// | ||||
2 | // | ||||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||
4 | // See https://llvm.org/LICENSE.txt for license information. | ||||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||
6 | // | ||||
7 | //===----------------------------------------------------------------------===// | ||||
8 | // | ||||
9 | // This file is a part of DataFlowSanitizer. | ||||
10 | // | ||||
11 | // DataFlowSanitizer runtime. This file defines the public interface to | ||||
12 | // DataFlowSanitizer as well as the definition of certain runtime functions | ||||
13 | // called automatically by the compiler (specifically the instrumentation pass | ||||
14 | // in llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp). | ||||
15 | // | ||||
16 | // The public interface is defined in include/sanitizer/dfsan_interface.h whose | ||||
17 | // functions are prefixed dfsan_ while the compiler interface functions are | ||||
18 | // prefixed __dfsan_. | ||||
19 | //===----------------------------------------------------------------------===// | ||||
20 | |||||
21 | #include "dfsan/dfsan.h" | ||||
22 | |||||
23 | #include "dfsan/dfsan_chained_origin_depot.h" | ||||
24 | #include "dfsan/dfsan_flags.h" | ||||
25 | #include "dfsan/dfsan_origin.h" | ||||
26 | #include "dfsan/dfsan_thread.h" | ||||
27 | #include "sanitizer_common/sanitizer_atomic.h" | ||||
28 | #include "sanitizer_common/sanitizer_common.h" | ||||
29 | #include "sanitizer_common/sanitizer_file.h" | ||||
30 | #include "sanitizer_common/sanitizer_flag_parser.h" | ||||
31 | #include "sanitizer_common/sanitizer_flags.h" | ||||
32 | #include "sanitizer_common/sanitizer_internal_defs.h" | ||||
33 | #include "sanitizer_common/sanitizer_libc.h" | ||||
34 | #include "sanitizer_common/sanitizer_report_decorator.h" | ||||
35 | #include "sanitizer_common/sanitizer_stacktrace.h" | ||||
36 | |||||
37 | using namespace __dfsan; | ||||
38 | |||||
39 | Flags __dfsan::flags_data; | ||||
40 | |||||
41 | // The size of TLS variables. These constants must be kept in sync with the ones | ||||
42 | // in DataFlowSanitizer.cpp. | ||||
43 | static const int kDFsanArgTlsSize = 800; | ||||
44 | static const int kDFsanRetvalTlsSize = 800; | ||||
45 | static const int kDFsanArgOriginTlsSize = 800; | ||||
46 | |||||
47 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) THREADLOCAL__thread u64 | ||||
48 | __dfsan_retval_tls[kDFsanRetvalTlsSize / sizeof(u64)]; | ||||
49 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) THREADLOCAL__thread u32 __dfsan_retval_origin_tls; | ||||
50 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) THREADLOCAL__thread u64 | ||||
51 | __dfsan_arg_tls[kDFsanArgTlsSize / sizeof(u64)]; | ||||
52 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) THREADLOCAL__thread u32 | ||||
53 | __dfsan_arg_origin_tls[kDFsanArgOriginTlsSize / sizeof(u32)]; | ||||
54 | |||||
55 | // Instrumented code may set this value in terms of -dfsan-track-origins. | ||||
56 | // * undefined or 0: do not track origins. | ||||
57 | // * 1: track origins at memory store operations. | ||||
58 | // * 2: track origins at memory load and store operations. | ||||
59 | // TODO: track callsites. | ||||
60 | extern "C" SANITIZER_WEAK_ATTRIBUTE__attribute__((weak)) const int __dfsan_track_origins; | ||||
61 | |||||
62 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) int dfsan_get_track_origins() { | ||||
63 | return &__dfsan_track_origins ? __dfsan_track_origins : 0; | ||||
64 | } | ||||
65 | |||||
66 | // On Linux/x86_64, memory is laid out as follows: | ||||
67 | // | ||||
68 | // +--------------------+ 0x800000000000 (top of memory) | ||||
69 | // | application 3 | | ||||
70 | // +--------------------+ 0x700000000000 | ||||
71 | // | invalid | | ||||
72 | // +--------------------+ 0x610000000000 | ||||
73 | // | origin 1 | | ||||
74 | // +--------------------+ 0x600000000000 | ||||
75 | // | application 2 | | ||||
76 | // +--------------------+ 0x510000000000 | ||||
77 | // | shadow 1 | | ||||
78 | // +--------------------+ 0x500000000000 | ||||
79 | // | invalid | | ||||
80 | // +--------------------+ 0x400000000000 | ||||
81 | // | origin 3 | | ||||
82 | // +--------------------+ 0x300000000000 | ||||
83 | // | shadow 3 | | ||||
84 | // +--------------------+ 0x200000000000 | ||||
85 | // | origin 2 | | ||||
86 | // +--------------------+ 0x110000000000 | ||||
87 | // | invalid | | ||||
88 | // +--------------------+ 0x100000000000 | ||||
89 | // | shadow 2 | | ||||
90 | // +--------------------+ 0x010000000000 | ||||
91 | // | application 1 | | ||||
92 | // +--------------------+ 0x000000000000 | ||||
93 | // | ||||
94 | // MEM_TO_SHADOW(mem) = mem ^ 0x500000000000 | ||||
95 | // SHADOW_TO_ORIGIN(shadow) = shadow + 0x100000000000 | ||||
96 | |||||
97 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) | ||||
98 | dfsan_label __dfsan_union_load(const dfsan_label *ls, uptr n) { | ||||
99 | dfsan_label label = ls[0]; | ||||
100 | for (uptr i = 1; i != n; ++i) | ||||
101 | label |= ls[i]; | ||||
102 | return label; | ||||
103 | } | ||||
104 | |||||
105 | // Return the union of all the n labels from addr at the high 32 bit, and the | ||||
106 | // origin of the first taint byte at the low 32 bit. | ||||
107 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) u64 | ||||
108 | __dfsan_load_label_and_origin(const void *addr, uptr n) { | ||||
109 | dfsan_label label = 0; | ||||
110 | u64 ret = 0; | ||||
111 | uptr p = (uptr)addr; | ||||
112 | dfsan_label *s = shadow_for((void *)p); | ||||
113 | for (uptr i = 0; i < n; ++i) { | ||||
114 | dfsan_label l = s[i]; | ||||
115 | if (!l) | ||||
116 | continue; | ||||
117 | label |= l; | ||||
118 | if (!ret) | ||||
119 | ret = *(dfsan_origin *)origin_for((void *)(p + i)); | ||||
120 | } | ||||
121 | return ret | (u64)label << 32; | ||||
122 | } | ||||
123 | |||||
124 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) | ||||
125 | void __dfsan_unimplemented(char *fname) { | ||||
126 | if (flags().warn_unimplemented) | ||||
127 | Report("WARNING: DataFlowSanitizer: call to uninstrumented function %s\n", | ||||
128 | fname); | ||||
129 | } | ||||
130 | |||||
131 | // Use '-mllvm -dfsan-debug-nonzero-labels' and break on this function | ||||
132 | // to try to figure out where labels are being introduced in a nominally | ||||
133 | // label-free program. | ||||
134 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) void __dfsan_nonzero_label() { | ||||
135 | if (flags().warn_nonzero_labels) | ||||
136 | Report("WARNING: DataFlowSanitizer: saw nonzero label\n"); | ||||
137 | } | ||||
138 | |||||
139 | // Indirect call to an uninstrumented vararg function. We don't have a way of | ||||
140 | // handling these at the moment. | ||||
141 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) void | ||||
142 | __dfsan_vararg_wrapper(const char *fname) { | ||||
143 | Report("FATAL: DataFlowSanitizer: unsupported indirect call to vararg " | ||||
144 | "function %s\n", fname); | ||||
145 | Die(); | ||||
146 | } | ||||
147 | |||||
148 | // Resolves the union of two labels. | ||||
149 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) dfsan_label | ||||
150 | dfsan_union(dfsan_label l1, dfsan_label l2) { | ||||
151 | return l1 | l2; | ||||
152 | } | ||||
153 | |||||
154 | static const uptr kOriginAlign = sizeof(dfsan_origin); | ||||
155 | static const uptr kOriginAlignMask = ~(kOriginAlign - 1UL); | ||||
156 | |||||
157 | static uptr OriginAlignUp(uptr u) { | ||||
158 | return (u + kOriginAlign - 1) & kOriginAlignMask; | ||||
159 | } | ||||
160 | |||||
161 | static uptr OriginAlignDown(uptr u) { return u & kOriginAlignMask; } | ||||
162 | |||||
163 | // Return the origin of the first taint byte in the size bytes from the address | ||||
164 | // addr. | ||||
165 | static dfsan_origin GetOriginIfTainted(uptr addr, uptr size) { | ||||
166 | for (uptr i = 0; i < size; ++i, ++addr) { | ||||
167 | dfsan_label *s = shadow_for((void *)addr); | ||||
168 | |||||
169 | if (*s) { | ||||
170 | // Validate address region. | ||||
171 | CHECK(MEM_IS_SHADOW(s))do { __sanitizer::u64 v1 = (__sanitizer::u64)((addr_is_type(( uptr)(s), MappingDesc::SHADOW))); __sanitizer::u64 v2 = (__sanitizer ::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer ::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 171, "(" "(addr_is_type((uptr)(s), MappingDesc::SHADOW))" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
172 | return *(dfsan_origin *)origin_for((void *)addr); | ||||
173 | } | ||||
174 | } | ||||
175 | return 0; | ||||
176 | } | ||||
177 | |||||
178 | // For platforms which support slow unwinder only, we need to restrict the store | ||||
179 | // context size to 1, basically only storing the current pc, because the slow | ||||
180 | // unwinder which is based on libunwind is not async signal safe and causes | ||||
181 | // random freezes in forking applications as well as in signal handlers. | ||||
182 | // DFSan supports only Linux. So we do not restrict the store context size. | ||||
183 | #define GET_STORE_STACK_TRACE_PC_BP(pc, bp)BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size); \ | ||||
184 | BufferedStackTrace stack; \ | ||||
185 | stack.Unwind(pc, bp, nullptr, true, flags().store_context_size); | ||||
186 | |||||
187 | #define PRINT_CALLER_STACK_TRACE{ uptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; uptr local_stack ; uptr sp = (uptr)&local_stack; (void)sp; BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size ); stack.Print(); } \ | ||||
188 | { \ | ||||
189 | GET_CALLER_PC_BP_SPuptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; uptr local_stack ; uptr sp = (uptr)&local_stack; \ | ||||
190 | (void)sp; \ | ||||
191 | GET_STORE_STACK_TRACE_PC_BP(pc, bp)BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size); \ | ||||
192 | stack.Print(); \ | ||||
193 | } | ||||
194 | |||||
195 | // Return a chain with the previous ID id and the current stack. | ||||
196 | // from_init = true if this is the first chain of an origin tracking path. | ||||
197 | static u32 ChainOrigin(u32 id, StackTrace *stack, bool from_init = false) { | ||||
198 | // StackDepot is not async signal safe. Do not create new chains in a signal | ||||
199 | // handler. | ||||
200 | DFsanThread *t = GetCurrentThread(); | ||||
201 | if (t && t->InSignalHandler()) | ||||
202 | return id; | ||||
203 | |||||
204 | // As an optimization the origin of an application byte is updated only when | ||||
205 | // its shadow is non-zero. Because we are only interested in the origins of | ||||
206 | // taint labels, it does not matter what origin a zero label has. This reduces | ||||
207 | // memory write cost. MSan does similar optimization. The following invariant | ||||
208 | // may not hold because of some bugs. We check the invariant to help debug. | ||||
209 | if (!from_init
| ||||
210 | Printf(" DFSan found invalid origin invariant\n"); | ||||
211 | PRINT_CALLER_STACK_TRACE{ uptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; uptr local_stack ; uptr sp = (uptr)&local_stack; (void)sp; BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size ); stack.Print(); } | ||||
212 | } | ||||
213 | |||||
214 | Origin o = Origin::FromRawId(id); | ||||
215 | stack->tag = StackTrace::TAG_UNKNOWN; | ||||
216 | Origin chained = Origin::CreateChainedOrigin(o, stack); | ||||
217 | return chained.raw_id(); | ||||
218 | } | ||||
219 | |||||
220 | static void ChainAndWriteOriginIfTainted(uptr src, uptr size, uptr dst, | ||||
221 | StackTrace *stack) { | ||||
222 | dfsan_origin o = GetOriginIfTainted(src, size); | ||||
223 | if (o) { | ||||
224 | o = ChainOrigin(o, stack); | ||||
225 | *(dfsan_origin *)origin_for((void *)dst) = o; | ||||
226 | } | ||||
227 | } | ||||
228 | |||||
229 | // Copy the origins of the size bytes from src to dst. The source and target | ||||
230 | // memory ranges cannot be overlapped. This is used by memcpy. stack records the | ||||
231 | // stack trace of the memcpy. When dst and src are not 4-byte aligned properly, | ||||
232 | // origins at the unaligned address boundaries may be overwritten because four | ||||
233 | // contiguous bytes share the same origin. | ||||
234 | static void CopyOrigin(const void *dst, const void *src, uptr size, | ||||
235 | StackTrace *stack) { | ||||
236 | uptr d = (uptr)dst; | ||||
237 | uptr beg = OriginAlignDown(d); | ||||
238 | // Copy left unaligned origin if that memory is tainted. | ||||
239 | if (beg < d) { | ||||
240 | ChainAndWriteOriginIfTainted((uptr)src, beg + kOriginAlign - d, beg, stack); | ||||
241 | beg += kOriginAlign; | ||||
242 | } | ||||
243 | |||||
244 | uptr end = OriginAlignDown(d + size); | ||||
245 | // If both ends fall into the same 4-byte slot, we are done. | ||||
246 | if (end < beg) | ||||
247 | return; | ||||
248 | |||||
249 | // Copy right unaligned origin if that memory is tainted. | ||||
250 | if (end < d + size) | ||||
251 | ChainAndWriteOriginIfTainted((uptr)src + (end - d), (d + size) - end, end, | ||||
252 | stack); | ||||
253 | |||||
254 | if (beg >= end) | ||||
255 | return; | ||||
256 | |||||
257 | // Align src up. | ||||
258 | uptr src_a = OriginAlignUp((uptr)src); | ||||
259 | dfsan_origin *src_o = origin_for((void *)src_a); | ||||
260 | u32 *src_s = (u32 *)shadow_for((void *)src_a); | ||||
261 | dfsan_origin *src_end = origin_for((void *)(src_a + (end - beg))); | ||||
262 | dfsan_origin *dst_o = origin_for((void *)beg); | ||||
263 | dfsan_origin last_src_o = 0; | ||||
264 | dfsan_origin last_dst_o = 0; | ||||
265 | for (; src_o < src_end; ++src_o, ++src_s, ++dst_o) { | ||||
266 | if (!*src_s) | ||||
267 | continue; | ||||
268 | if (*src_o != last_src_o) { | ||||
269 | last_src_o = *src_o; | ||||
270 | last_dst_o = ChainOrigin(last_src_o, stack); | ||||
271 | } | ||||
272 | *dst_o = last_dst_o; | ||||
273 | } | ||||
274 | } | ||||
275 | |||||
276 | // Copy the origins of the size bytes from src to dst. The source and target | ||||
277 | // memory ranges may be overlapped. So the copy is done in a reverse order. | ||||
278 | // This is used by memmove. stack records the stack trace of the memmove. | ||||
279 | static void ReverseCopyOrigin(const void *dst, const void *src, uptr size, | ||||
280 | StackTrace *stack) { | ||||
281 | uptr d = (uptr)dst; | ||||
282 | uptr end = OriginAlignDown(d + size); | ||||
283 | |||||
284 | // Copy right unaligned origin if that memory is tainted. | ||||
285 | if (end < d + size) | ||||
286 | ChainAndWriteOriginIfTainted((uptr)src + (end - d), (d + size) - end, end, | ||||
287 | stack); | ||||
288 | |||||
289 | uptr beg = OriginAlignDown(d); | ||||
290 | |||||
291 | if (beg + kOriginAlign < end) { | ||||
292 | // Align src up. | ||||
293 | uptr src_a = OriginAlignUp((uptr)src); | ||||
294 | void *src_end = (void *)(src_a + end - beg - kOriginAlign); | ||||
295 | dfsan_origin *src_end_o = origin_for(src_end); | ||||
296 | u32 *src_end_s = (u32 *)shadow_for(src_end); | ||||
297 | dfsan_origin *src_begin_o = origin_for((void *)src_a); | ||||
298 | dfsan_origin *dst = origin_for((void *)(end - kOriginAlign)); | ||||
299 | dfsan_origin last_src_o = 0; | ||||
300 | dfsan_origin last_dst_o = 0; | ||||
301 | for (; src_end_o >= src_begin_o; --src_end_o, --src_end_s, --dst) { | ||||
302 | if (!*src_end_s) | ||||
303 | continue; | ||||
304 | if (*src_end_o != last_src_o) { | ||||
305 | last_src_o = *src_end_o; | ||||
306 | last_dst_o = ChainOrigin(last_src_o, stack); | ||||
307 | } | ||||
308 | *dst = last_dst_o; | ||||
309 | } | ||||
310 | } | ||||
311 | |||||
312 | // Copy left unaligned origin if that memory is tainted. | ||||
313 | if (beg < d) | ||||
314 | ChainAndWriteOriginIfTainted((uptr)src, beg + kOriginAlign - d, beg, stack); | ||||
315 | } | ||||
316 | |||||
317 | // Copy or move the origins of the len bytes from src to dst. The source and | ||||
318 | // target memory ranges may or may not be overlapped. This is used by memory | ||||
319 | // transfer operations. stack records the stack trace of the memory transfer | ||||
320 | // operation. | ||||
321 | static void MoveOrigin(const void *dst, const void *src, uptr size, | ||||
322 | StackTrace *stack) { | ||||
323 | // Validate address regions. | ||||
324 | if (!MEM_IS_SHADOW(shadow_for(dst))addr_is_type((uptr)(shadow_for(dst)), MappingDesc::SHADOW) || | ||||
325 | !MEM_IS_SHADOW(shadow_for((void *)((uptr)dst + size)))addr_is_type((uptr)(shadow_for((void *)((uptr)dst + size))), MappingDesc ::SHADOW) || | ||||
326 | !MEM_IS_SHADOW(shadow_for(src))addr_is_type((uptr)(shadow_for(src)), MappingDesc::SHADOW) || | ||||
327 | !MEM_IS_SHADOW(shadow_for((void *)((uptr)src + size)))addr_is_type((uptr)(shadow_for((void *)((uptr)src + size))), MappingDesc ::SHADOW)) { | ||||
328 | CHECK(false)do { __sanitizer::u64 v1 = (__sanitizer::u64)((false)); __sanitizer ::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 328, "(" "(false)" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
329 | return; | ||||
330 | } | ||||
331 | // If destination origin range overlaps with source origin range, move | ||||
332 | // origins by copying origins in a reverse order; otherwise, copy origins in | ||||
333 | // a normal order. The orders of origin transfer are consistent with the | ||||
334 | // orders of how memcpy and memmove transfer user data. | ||||
335 | uptr src_aligned_beg = reinterpret_cast<uptr>(src) & ~3UL; | ||||
336 | uptr src_aligned_end = (reinterpret_cast<uptr>(src) + size) & ~3UL; | ||||
337 | uptr dst_aligned_beg = reinterpret_cast<uptr>(dst) & ~3UL; | ||||
338 | if (dst_aligned_beg < src_aligned_end && dst_aligned_beg >= src_aligned_beg) | ||||
339 | return ReverseCopyOrigin(dst, src, size, stack); | ||||
340 | return CopyOrigin(dst, src, size, stack); | ||||
341 | } | ||||
342 | |||||
343 | // Set the size bytes from the addres dst to be the origin value. | ||||
344 | static void SetOrigin(const void *dst, uptr size, u32 origin) { | ||||
345 | if (size == 0) | ||||
346 | return; | ||||
347 | |||||
348 | // Origin mapping is 4 bytes per 4 bytes of application memory. | ||||
349 | // Here we extend the range such that its left and right bounds are both | ||||
350 | // 4 byte aligned. | ||||
351 | uptr x = unaligned_origin_for((uptr)dst); | ||||
352 | uptr beg = OriginAlignDown(x); | ||||
353 | uptr end = OriginAlignUp(x + size); // align up. | ||||
354 | u64 origin64 = ((u64)origin << 32) | origin; | ||||
355 | // This is like memset, but the value is 32-bit. We unroll by 2 to write | ||||
356 | // 64 bits at once. May want to unroll further to get 128-bit stores. | ||||
357 | if (beg & 7ULL) { | ||||
358 | if (*(u32 *)beg != origin) | ||||
359 | *(u32 *)beg = origin; | ||||
360 | beg += 4; | ||||
361 | } | ||||
362 | for (uptr addr = beg; addr < (end & ~7UL); addr += 8) { | ||||
363 | if (*(u64 *)addr == origin64) | ||||
364 | continue; | ||||
365 | *(u64 *)addr = origin64; | ||||
366 | } | ||||
367 | if (end & 7ULL) | ||||
368 | if (*(u32 *)(end - kOriginAlign) != origin) | ||||
369 | *(u32 *)(end - kOriginAlign) = origin; | ||||
370 | } | ||||
371 | |||||
372 | static void WriteShadowInRange(dfsan_label label, uptr beg_shadow_addr, | ||||
373 | uptr end_shadow_addr) { | ||||
374 | // TODO: After changing dfsan_label to 8bit, use internal_memset when label | ||||
375 | // is not 0. | ||||
376 | dfsan_label *labelp = (dfsan_label *)beg_shadow_addr; | ||||
377 | if (label) { | ||||
378 | for (; (uptr)labelp < end_shadow_addr; ++labelp) *labelp = label; | ||||
379 | return; | ||||
380 | } | ||||
381 | |||||
382 | for (; (uptr)labelp < end_shadow_addr; ++labelp) { | ||||
383 | // Don't write the label if it is already the value we need it to be. | ||||
384 | // In a program where most addresses are not labeled, it is common that | ||||
385 | // a page of shadow memory is entirely zeroed. The Linux copy-on-write | ||||
386 | // implementation will share all of the zeroed pages, making a copy of a | ||||
387 | // page when any value is written. The un-sharing will happen even if | ||||
388 | // the value written does not change the value in memory. Avoiding the | ||||
389 | // write when both |label| and |*labelp| are zero dramatically reduces | ||||
390 | // the amount of real memory used by large programs. | ||||
391 | if (!*labelp) | ||||
392 | continue; | ||||
393 | |||||
394 | *labelp = 0; | ||||
395 | } | ||||
396 | } | ||||
397 | |||||
398 | static void WriteShadowWithSize(dfsan_label label, uptr shadow_addr, | ||||
399 | uptr size) { | ||||
400 | WriteShadowInRange(label, shadow_addr, shadow_addr + size * sizeof(label)); | ||||
401 | } | ||||
402 | |||||
403 | #define RET_CHAIN_ORIGIN(id)uptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; uptr local_stack ; uptr sp = (uptr)&local_stack; (void)sp; BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size );; return ChainOrigin(id, &stack); \ | ||||
404 | GET_CALLER_PC_BP_SPuptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; uptr local_stack ; uptr sp = (uptr)&local_stack; \ | ||||
405 | (void)sp; \ | ||||
406 | GET_STORE_STACK_TRACE_PC_BP(pc, bp)BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size);; \ | ||||
407 | return ChainOrigin(id, &stack); | ||||
408 | |||||
409 | // Return a new origin chain with the previous ID id and the current stack | ||||
410 | // trace. | ||||
411 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) dfsan_origin | ||||
412 | __dfsan_chain_origin(dfsan_origin id) { | ||||
413 | RET_CHAIN_ORIGIN(id)uptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; uptr local_stack ; uptr sp = (uptr)&local_stack; (void)sp; BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size );; return ChainOrigin(id, &stack); | ||||
414 | } | ||||
415 | |||||
416 | // Return a new origin chain with the previous ID id and the current stack | ||||
417 | // trace if the label is tainted. | ||||
418 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) dfsan_origin | ||||
419 | __dfsan_chain_origin_if_tainted(dfsan_label label, dfsan_origin id) { | ||||
420 | if (!label) | ||||
421 | return id; | ||||
422 | RET_CHAIN_ORIGIN(id)uptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; uptr local_stack ; uptr sp = (uptr)&local_stack; (void)sp; BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size );; return ChainOrigin(id, &stack); | ||||
423 | } | ||||
424 | |||||
425 | // Copy or move the origins of the len bytes from src to dst. | ||||
426 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) void __dfsan_mem_origin_transfer( | ||||
427 | const void *dst, const void *src, uptr len) { | ||||
428 | if (src == dst) | ||||
429 | return; | ||||
430 | GET_CALLER_PC_BPuptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; | ||||
431 | GET_STORE_STACK_TRACE_PC_BP(pc, bp)BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size);; | ||||
432 | MoveOrigin(dst, src, len, &stack); | ||||
433 | } | ||||
434 | |||||
435 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) void dfsan_mem_origin_transfer(const void *dst, | ||||
436 | const void *src, | ||||
437 | uptr len) { | ||||
438 | __dfsan_mem_origin_transfer(dst, src, len); | ||||
439 | } | ||||
440 | |||||
441 | namespace __dfsan { | ||||
442 | |||||
443 | bool dfsan_inited = false; | ||||
444 | bool dfsan_init_is_running = false; | ||||
445 | |||||
446 | void dfsan_copy_memory(void *dst, const void *src, uptr size) { | ||||
447 | internal_memcpy(dst, src, size); | ||||
448 | internal_memcpy((void *)shadow_for(dst), (const void *)shadow_for(src), | ||||
449 | size * sizeof(dfsan_label)); | ||||
450 | if (dfsan_get_track_origins()) | ||||
451 | dfsan_mem_origin_transfer(dst, src, size); | ||||
452 | } | ||||
453 | |||||
454 | } // namespace __dfsan | ||||
455 | |||||
456 | // If the label s is tainted, set the size bytes from the address p to be a new | ||||
457 | // origin chain with the previous ID o and the current stack trace. This is | ||||
458 | // used by instrumentation to reduce code size when too much code is inserted. | ||||
459 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) void __dfsan_maybe_store_origin( | ||||
460 | dfsan_label s, void *p, uptr size, dfsan_origin o) { | ||||
461 | if (UNLIKELY(s)__builtin_expect(!!(s), 0)) { | ||||
462 | GET_CALLER_PC_BP_SPuptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; uptr local_stack ; uptr sp = (uptr)&local_stack; | ||||
463 | (void)sp; | ||||
464 | GET_STORE_STACK_TRACE_PC_BP(pc, bp)BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size);; | ||||
465 | SetOrigin(p, size, ChainOrigin(o, &stack)); | ||||
466 | } | ||||
467 | } | ||||
468 | |||||
469 | // Releases the pages within the origin address range. | ||||
470 | static void ReleaseOrigins(void *addr, uptr size) { | ||||
471 | const uptr beg_origin_addr = (uptr)__dfsan::origin_for(addr); | ||||
472 | const void *end_addr = (void *)((uptr)addr + size); | ||||
473 | const uptr end_origin_addr = (uptr)__dfsan::origin_for(end_addr); | ||||
474 | |||||
475 | if (end_origin_addr - beg_origin_addr < | ||||
476 | common_flags()->clear_shadow_mmap_threshold) | ||||
477 | return; | ||||
478 | |||||
479 | const uptr page_size = GetPageSizeCached(); | ||||
480 | const uptr beg_aligned = RoundUpTo(beg_origin_addr, page_size); | ||||
481 | const uptr end_aligned = RoundDownTo(end_origin_addr, page_size); | ||||
482 | |||||
483 | if (!MmapFixedSuperNoReserve(beg_aligned, end_aligned - beg_aligned)) | ||||
484 | Die(); | ||||
485 | } | ||||
486 | |||||
487 | // Releases the pages within the shadow address range, and sets | ||||
488 | // the shadow addresses not on the pages to be 0. | ||||
489 | static void ReleaseOrClearShadows(void *addr, uptr size) { | ||||
490 | const uptr beg_shadow_addr = (uptr)__dfsan::shadow_for(addr); | ||||
491 | const void *end_addr = (void *)((uptr)addr + size); | ||||
492 | const uptr end_shadow_addr = (uptr)__dfsan::shadow_for(end_addr); | ||||
493 | |||||
494 | if (end_shadow_addr - beg_shadow_addr < | ||||
495 | common_flags()->clear_shadow_mmap_threshold) | ||||
496 | return WriteShadowWithSize(0, beg_shadow_addr, size); | ||||
497 | |||||
498 | const uptr page_size = GetPageSizeCached(); | ||||
499 | const uptr beg_aligned = RoundUpTo(beg_shadow_addr, page_size); | ||||
500 | const uptr end_aligned = RoundDownTo(end_shadow_addr, page_size); | ||||
501 | |||||
502 | if (beg_aligned >= end_aligned) { | ||||
503 | WriteShadowWithSize(0, beg_shadow_addr, size); | ||||
504 | } else { | ||||
505 | if (beg_aligned != beg_shadow_addr) | ||||
506 | WriteShadowInRange(0, beg_shadow_addr, beg_aligned); | ||||
507 | if (end_aligned != end_shadow_addr) | ||||
508 | WriteShadowInRange(0, end_aligned, end_shadow_addr); | ||||
509 | if (!MmapFixedSuperNoReserve(beg_aligned, end_aligned - beg_aligned)) | ||||
510 | Die(); | ||||
511 | } | ||||
512 | } | ||||
513 | |||||
514 | void SetShadow(dfsan_label label, void *addr, uptr size, dfsan_origin origin) { | ||||
515 | if (0 != label) { | ||||
516 | const uptr beg_shadow_addr = (uptr)__dfsan::shadow_for(addr); | ||||
517 | WriteShadowWithSize(label, beg_shadow_addr, size); | ||||
518 | if (dfsan_get_track_origins()) | ||||
519 | SetOrigin(addr, size, origin); | ||||
520 | return; | ||||
521 | } | ||||
522 | |||||
523 | if (dfsan_get_track_origins()) | ||||
524 | ReleaseOrigins(addr, size); | ||||
525 | |||||
526 | ReleaseOrClearShadows(addr, size); | ||||
527 | } | ||||
528 | |||||
529 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) void __dfsan_set_label( | ||||
530 | dfsan_label label, dfsan_origin origin, void *addr, uptr size) { | ||||
531 | SetShadow(label, addr, size, origin); | ||||
532 | } | ||||
533 | |||||
534 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) | ||||
535 | void dfsan_set_label(dfsan_label label, void *addr, uptr size) { | ||||
536 | dfsan_origin init_origin = 0; | ||||
537 | if (label && dfsan_get_track_origins()) { | ||||
| |||||
538 | GET_CALLER_PC_BPuptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; | ||||
539 | GET_STORE_STACK_TRACE_PC_BP(pc, bp)BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size);; | ||||
540 | init_origin = ChainOrigin(0, &stack, true); | ||||
541 | } | ||||
542 | SetShadow(label, addr, size, init_origin); | ||||
543 | } | ||||
544 | |||||
545 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) | ||||
546 | void dfsan_add_label(dfsan_label label, void *addr, uptr size) { | ||||
547 | if (0 == label) | ||||
548 | return; | ||||
549 | |||||
550 | if (dfsan_get_track_origins()) { | ||||
551 | GET_CALLER_PC_BPuptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; | ||||
552 | GET_STORE_STACK_TRACE_PC_BP(pc, bp)BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size);; | ||||
553 | dfsan_origin init_origin = ChainOrigin(0, &stack, true); | ||||
554 | SetOrigin(addr, size, init_origin); | ||||
555 | } | ||||
556 | |||||
557 | for (dfsan_label *labelp = shadow_for(addr); size != 0; --size, ++labelp) | ||||
558 | *labelp |= label; | ||||
559 | } | ||||
560 | |||||
561 | // Unlike the other dfsan interface functions the behavior of this function | ||||
562 | // depends on the label of one of its arguments. Hence it is implemented as a | ||||
563 | // custom function. | ||||
564 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) dfsan_label | ||||
565 | __dfsw_dfsan_get_label(long data, dfsan_label data_label, | ||||
566 | dfsan_label *ret_label) { | ||||
567 | *ret_label = 0; | ||||
568 | return data_label; | ||||
569 | } | ||||
570 | |||||
571 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) dfsan_label __dfso_dfsan_get_label( | ||||
572 | long data, dfsan_label data_label, dfsan_label *ret_label, | ||||
573 | dfsan_origin data_origin, dfsan_origin *ret_origin) { | ||||
574 | *ret_label = 0; | ||||
575 | *ret_origin = 0; | ||||
576 | return data_label; | ||||
577 | } | ||||
578 | |||||
579 | // This function is used if dfsan_get_origin is called when origin tracking is | ||||
580 | // off. | ||||
581 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) dfsan_origin __dfsw_dfsan_get_origin( | ||||
582 | long data, dfsan_label data_label, dfsan_label *ret_label) { | ||||
583 | *ret_label = 0; | ||||
584 | return 0; | ||||
585 | } | ||||
586 | |||||
587 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) dfsan_origin __dfso_dfsan_get_origin( | ||||
588 | long data, dfsan_label data_label, dfsan_label *ret_label, | ||||
589 | dfsan_origin data_origin, dfsan_origin *ret_origin) { | ||||
590 | *ret_label = 0; | ||||
591 | *ret_origin = 0; | ||||
592 | return data_origin; | ||||
593 | } | ||||
594 | |||||
595 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) dfsan_label | ||||
596 | dfsan_read_label(const void *addr, uptr size) { | ||||
597 | if (size == 0) | ||||
598 | return 0; | ||||
599 | return __dfsan_union_load(shadow_for(addr), size); | ||||
600 | } | ||||
601 | |||||
602 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) dfsan_origin | ||||
603 | dfsan_read_origin_of_first_taint(const void *addr, uptr size) { | ||||
604 | return GetOriginIfTainted((uptr)addr, size); | ||||
605 | } | ||||
606 | |||||
607 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) void dfsan_set_label_origin(dfsan_label label, | ||||
608 | dfsan_origin origin, | ||||
609 | void *addr, | ||||
610 | uptr size) { | ||||
611 | __dfsan_set_label(label, origin, addr, size); | ||||
612 | } | ||||
613 | |||||
614 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) int | ||||
615 | dfsan_has_label(dfsan_label label, dfsan_label elem) { | ||||
616 | return (label & elem) == elem; | ||||
617 | } | ||||
618 | |||||
619 | class Decorator : public __sanitizer::SanitizerCommonDecorator { | ||||
620 | public: | ||||
621 | Decorator() : SanitizerCommonDecorator() {} | ||||
622 | const char *Origin() const { return Magenta(); } | ||||
623 | }; | ||||
624 | |||||
625 | namespace { | ||||
626 | |||||
627 | void PrintNoOriginTrackingWarning() { | ||||
628 | Decorator d; | ||||
629 | Printf( | ||||
630 | " %sDFSan: origin tracking is not enabled. Did you specify the " | ||||
631 | "-dfsan-track-origins=1 option?%s\n", | ||||
632 | d.Warning(), d.Default()); | ||||
633 | } | ||||
634 | |||||
635 | void PrintNoTaintWarning(const void *address) { | ||||
636 | Decorator d; | ||||
637 | Printf(" %sDFSan: no tainted value at %x%s\n", d.Warning(), address, | ||||
638 | d.Default()); | ||||
639 | } | ||||
640 | |||||
641 | void PrintInvalidOriginWarning(dfsan_label label, const void *address) { | ||||
642 | Decorator d; | ||||
643 | Printf( | ||||
644 | " %sTaint value 0x%x (at %p) has invalid origin tracking. This can " | ||||
645 | "be a DFSan bug.%s\n", | ||||
646 | d.Warning(), label, address, d.Default()); | ||||
647 | } | ||||
648 | |||||
649 | bool PrintOriginTraceToStr(const void *addr, const char *description, | ||||
650 | InternalScopedString *out) { | ||||
651 | CHECK(out)do { __sanitizer::u64 v1 = (__sanitizer::u64)((out)); __sanitizer ::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 651, "(" "(out)" ") " "!=" " (" "0" ")", v1, v2); } while ( false); | ||||
652 | CHECK(dfsan_get_track_origins())do { __sanitizer::u64 v1 = (__sanitizer::u64)((dfsan_get_track_origins ())); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 652, "(" "(dfsan_get_track_origins())" ") " "!=" " (" "0" ")" , v1, v2); } while (false); | ||||
653 | Decorator d; | ||||
654 | |||||
655 | const dfsan_label label = *__dfsan::shadow_for(addr); | ||||
656 | CHECK(label)do { __sanitizer::u64 v1 = (__sanitizer::u64)((label)); __sanitizer ::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 656, "(" "(label)" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
657 | |||||
658 | const dfsan_origin origin = *__dfsan::origin_for(addr); | ||||
659 | |||||
660 | out->append(" %sTaint value 0x%x (at %p) origin tracking (%s)%s\n", | ||||
661 | d.Origin(), label, addr, description ? description : "", | ||||
662 | d.Default()); | ||||
663 | |||||
664 | Origin o = Origin::FromRawId(origin); | ||||
665 | bool found = false; | ||||
666 | |||||
667 | while (o.isChainedOrigin()) { | ||||
668 | StackTrace stack; | ||||
669 | dfsan_origin origin_id = o.raw_id(); | ||||
670 | o = o.getNextChainedOrigin(&stack); | ||||
671 | if (o.isChainedOrigin()) | ||||
672 | out->append( | ||||
673 | " %sOrigin value: 0x%x, Taint value was stored to memory at%s\n", | ||||
674 | d.Origin(), origin_id, d.Default()); | ||||
675 | else | ||||
676 | out->append(" %sOrigin value: 0x%x, Taint value was created at%s\n", | ||||
677 | d.Origin(), origin_id, d.Default()); | ||||
678 | |||||
679 | // Includes a trailing newline, so no need to add it again. | ||||
680 | stack.PrintTo(out); | ||||
681 | found = true; | ||||
682 | } | ||||
683 | |||||
684 | return found; | ||||
685 | } | ||||
686 | |||||
687 | } // namespace | ||||
688 | |||||
689 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) void dfsan_print_origin_trace( | ||||
690 | const void *addr, const char *description) { | ||||
691 | if (!dfsan_get_track_origins()) { | ||||
692 | PrintNoOriginTrackingWarning(); | ||||
693 | return; | ||||
694 | } | ||||
695 | |||||
696 | const dfsan_label label = *__dfsan::shadow_for(addr); | ||||
697 | if (!label) { | ||||
698 | PrintNoTaintWarning(addr); | ||||
699 | return; | ||||
700 | } | ||||
701 | |||||
702 | InternalScopedString trace; | ||||
703 | bool success = PrintOriginTraceToStr(addr, description, &trace); | ||||
704 | |||||
705 | if (trace.length()) | ||||
706 | Printf("%s", trace.data()); | ||||
707 | |||||
708 | if (!success) | ||||
709 | PrintInvalidOriginWarning(label, addr); | ||||
710 | } | ||||
711 | |||||
712 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) size_t | ||||
713 | dfsan_sprint_origin_trace(const void *addr, const char *description, | ||||
714 | char *out_buf, size_t out_buf_size) { | ||||
715 | CHECK(out_buf)do { __sanitizer::u64 v1 = (__sanitizer::u64)((out_buf)); __sanitizer ::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 715, "(" "(out_buf)" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
716 | |||||
717 | if (!dfsan_get_track_origins()) { | ||||
718 | PrintNoOriginTrackingWarning(); | ||||
719 | return 0; | ||||
720 | } | ||||
721 | |||||
722 | const dfsan_label label = *__dfsan::shadow_for(addr); | ||||
723 | if (!label) { | ||||
724 | PrintNoTaintWarning(addr); | ||||
725 | return 0; | ||||
726 | } | ||||
727 | |||||
728 | InternalScopedString trace; | ||||
729 | bool success = PrintOriginTraceToStr(addr, description, &trace); | ||||
730 | |||||
731 | if (!success) { | ||||
732 | PrintInvalidOriginWarning(label, addr); | ||||
733 | return 0; | ||||
734 | } | ||||
735 | |||||
736 | if (out_buf_size) { | ||||
737 | internal_strncpy(out_buf, trace.data(), out_buf_size - 1); | ||||
738 | out_buf[out_buf_size - 1] = '\0'; | ||||
739 | } | ||||
740 | |||||
741 | return trace.length(); | ||||
742 | } | ||||
743 | |||||
744 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) dfsan_origin | ||||
745 | dfsan_get_init_origin(const void *addr) { | ||||
746 | if (!dfsan_get_track_origins()) | ||||
747 | return 0; | ||||
748 | |||||
749 | const dfsan_label label = *__dfsan::shadow_for(addr); | ||||
750 | if (!label) | ||||
751 | return 0; | ||||
752 | |||||
753 | const dfsan_origin origin = *__dfsan::origin_for(addr); | ||||
754 | |||||
755 | Origin o = Origin::FromRawId(origin); | ||||
756 | dfsan_origin origin_id = o.raw_id(); | ||||
757 | while (o.isChainedOrigin()) { | ||||
758 | StackTrace stack; | ||||
759 | origin_id = o.raw_id(); | ||||
760 | o = o.getNextChainedOrigin(&stack); | ||||
761 | } | ||||
762 | return origin_id; | ||||
763 | } | ||||
764 | |||||
765 | void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp, | ||||
766 | void *context, | ||||
767 | bool request_fast, | ||||
768 | u32 max_depth) { | ||||
769 | using namespace __dfsan; | ||||
770 | DFsanThread *t = GetCurrentThread(); | ||||
771 | if (!t || !StackTrace::WillUseFastUnwind(request_fast)) { | ||||
772 | return Unwind(max_depth, pc, bp, context, 0, 0, false); | ||||
773 | } | ||||
774 | Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), true); | ||||
775 | } | ||||
776 | |||||
777 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) void __sanitizer_print_stack_trace() { | ||||
778 | GET_CALLER_PC_BPuptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; | ||||
779 | GET_STORE_STACK_TRACE_PC_BP(pc, bp)BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size);; | ||||
780 | stack.Print(); | ||||
781 | } | ||||
782 | |||||
783 | extern "C" SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) size_t | ||||
784 | dfsan_sprint_stack_trace(char *out_buf, size_t out_buf_size) { | ||||
785 | CHECK(out_buf)do { __sanitizer::u64 v1 = (__sanitizer::u64)((out_buf)); __sanitizer ::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 785, "(" "(out_buf)" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
786 | GET_CALLER_PC_BPuptr bp = (__sanitizer::uptr) __builtin_frame_address(0); uptr pc = (__sanitizer::uptr) __builtin_return_address(0);; | ||||
787 | GET_STORE_STACK_TRACE_PC_BP(pc, bp)BufferedStackTrace stack; stack.Unwind(pc, bp, nullptr, true, flags().store_context_size);; | ||||
788 | return stack.PrintTo(out_buf, out_buf_size); | ||||
789 | } | ||||
790 | |||||
791 | void Flags::SetDefaults() { | ||||
792 | #define DFSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; | ||||
793 | #include "dfsan_flags.inc" | ||||
794 | #undef DFSAN_FLAG | ||||
795 | } | ||||
796 | |||||
797 | static void RegisterDfsanFlags(FlagParser *parser, Flags *f) { | ||||
798 | #define DFSAN_FLAG(Type, Name, DefaultValue, Description) \ | ||||
799 | RegisterFlag(parser, #Name, Description, &f->Name); | ||||
800 | #include "dfsan_flags.inc" | ||||
801 | #undef DFSAN_FLAG | ||||
802 | } | ||||
803 | |||||
804 | static void InitializeFlags() { | ||||
805 | SetCommonFlagsDefaults(); | ||||
806 | { | ||||
807 | CommonFlags cf; | ||||
808 | cf.CopyFrom(*common_flags()); | ||||
809 | cf.intercept_tls_get_addr = true; | ||||
810 | OverrideCommonFlags(cf); | ||||
811 | } | ||||
812 | flags().SetDefaults(); | ||||
813 | |||||
814 | FlagParser parser; | ||||
815 | RegisterCommonFlags(&parser); | ||||
816 | RegisterDfsanFlags(&parser, &flags()); | ||||
817 | parser.ParseStringFromEnv("DFSAN_OPTIONS"); | ||||
818 | InitializeCommonFlags(); | ||||
819 | if (Verbosity()) ReportUnrecognizedFlags(); | ||||
820 | if (common_flags()->help) parser.PrintFlagDescriptions(); | ||||
821 | } | ||||
822 | |||||
823 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) | ||||
824 | void dfsan_clear_arg_tls(uptr offset, uptr size) { | ||||
825 | internal_memset((void *)((uptr)__dfsan_arg_tls + offset), 0, size); | ||||
826 | } | ||||
827 | |||||
828 | SANITIZER_INTERFACE_ATTRIBUTE__attribute__((visibility("default"))) | ||||
829 | void dfsan_clear_thread_local_state() { | ||||
830 | internal_memset(__dfsan_arg_tls, 0, sizeof(__dfsan_arg_tls)); | ||||
831 | internal_memset(__dfsan_retval_tls, 0, sizeof(__dfsan_retval_tls)); | ||||
832 | |||||
833 | if (dfsan_get_track_origins()) { | ||||
834 | internal_memset(__dfsan_arg_origin_tls, 0, sizeof(__dfsan_arg_origin_tls)); | ||||
835 | internal_memset(&__dfsan_retval_origin_tls, 0, | ||||
836 | sizeof(__dfsan_retval_origin_tls)); | ||||
837 | } | ||||
838 | } | ||||
839 | |||||
840 | extern "C" void dfsan_flush() { | ||||
841 | const uptr maxVirtualAddress = GetMaxUserVirtualAddress(); | ||||
842 | for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { | ||||
843 | uptr start = kMemoryLayout[i].start; | ||||
844 | uptr end = kMemoryLayout[i].end; | ||||
845 | uptr size = end - start; | ||||
846 | MappingDesc::Type type = kMemoryLayout[i].type; | ||||
847 | |||||
848 | if (type != MappingDesc::SHADOW && type != MappingDesc::ORIGIN) | ||||
849 | continue; | ||||
850 | |||||
851 | // Check if the segment should be mapped based on platform constraints. | ||||
852 | if (start >= maxVirtualAddress) | ||||
853 | continue; | ||||
854 | |||||
855 | if (!MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name)) { | ||||
856 | Printf("FATAL: DataFlowSanitizer: failed to clear memory region\n"); | ||||
857 | Die(); | ||||
858 | } | ||||
859 | } | ||||
860 | } | ||||
861 | |||||
862 | // TODO: CheckMemoryLayoutSanity is based on msan. | ||||
863 | // Consider refactoring these into a shared implementation. | ||||
864 | static void CheckMemoryLayoutSanity() { | ||||
865 | uptr prev_end = 0; | ||||
866 | for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { | ||||
867 | uptr start = kMemoryLayout[i].start; | ||||
868 | uptr end = kMemoryLayout[i].end; | ||||
869 | MappingDesc::Type type = kMemoryLayout[i].type; | ||||
870 | CHECK_LT(start, end)do { __sanitizer::u64 v1 = (__sanitizer::u64)((start)); __sanitizer ::u64 v2 = (__sanitizer::u64)((end)); if (__builtin_expect(!! (!(v1 < v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 870, "(" "(start)" ") " "<" " (" "(end)" ")", v1, v2); } while (false); | ||||
871 | CHECK_EQ(prev_end, start)do { __sanitizer::u64 v1 = (__sanitizer::u64)((prev_end)); __sanitizer ::u64 v2 = (__sanitizer::u64)((start)); if (__builtin_expect( !!(!(v1 == v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 871, "(" "(prev_end)" ") " "==" " (" "(start)" ")", v1, v2) ; } while (false); | ||||
872 | CHECK(addr_is_type(start, type))do { __sanitizer::u64 v1 = (__sanitizer::u64)((addr_is_type(start , type))); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 872, "(" "(addr_is_type(start, type))" ") " "!=" " (" "0" ")" , v1, v2); } while (false); | ||||
873 | CHECK(addr_is_type((start + end) / 2, type))do { __sanitizer::u64 v1 = (__sanitizer::u64)((addr_is_type(( start + end) / 2, type))); __sanitizer::u64 v2 = (__sanitizer ::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer ::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 873, "(" "(addr_is_type((start + end) / 2, type))" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
874 | CHECK(addr_is_type(end - 1, type))do { __sanitizer::u64 v1 = (__sanitizer::u64)((addr_is_type(end - 1, type))); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 874, "(" "(addr_is_type(end - 1, type))" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
875 | if (type == MappingDesc::APP) { | ||||
876 | uptr addr = start; | ||||
877 | CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)))do { __sanitizer::u64 v1 = (__sanitizer::u64)((addr_is_type(( uptr)((((uptr)(addr)) ^ 0x500000000000ULL)), MappingDesc::SHADOW ))); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 877, "(" "(addr_is_type((uptr)((((uptr)(addr)) ^ 0x500000000000ULL)), MappingDesc::SHADOW))" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
878 | CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)))do { __sanitizer::u64 v1 = (__sanitizer::u64)((addr_is_type(( uptr)(((((uptr)((((uptr)((addr))) ^ 0x500000000000ULL))) + 0x100000000000ULL ))), MappingDesc::ORIGIN))); __sanitizer::u64 v2 = (__sanitizer ::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer ::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 878, "(" "(addr_is_type((uptr)(((((uptr)((((uptr)((addr))) ^ 0x500000000000ULL))) + 0x100000000000ULL))), MappingDesc::ORIGIN))" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
879 | CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)))do { __sanitizer::u64 v1 = (__sanitizer::u64)((((((uptr)((((uptr )((addr))) ^ 0x500000000000ULL))) + 0x100000000000ULL)))); __sanitizer ::u64 v2 = (__sanitizer::u64)(((((uptr)((((uptr)(addr)) ^ 0x500000000000ULL ))) + 0x100000000000ULL))); if (__builtin_expect(!!(!(v1 == v2 )), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 879, "(" "(((((uptr)((((uptr)((addr))) ^ 0x500000000000ULL))) + 0x100000000000ULL)))" ") " "==" " (" "((((uptr)((((uptr)(addr)) ^ 0x500000000000ULL))) + 0x100000000000ULL))" ")", v1, v2); } while (false); | ||||
880 | |||||
881 | addr = (start + end) / 2; | ||||
882 | CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)))do { __sanitizer::u64 v1 = (__sanitizer::u64)((addr_is_type(( uptr)((((uptr)(addr)) ^ 0x500000000000ULL)), MappingDesc::SHADOW ))); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 882, "(" "(addr_is_type((uptr)((((uptr)(addr)) ^ 0x500000000000ULL)), MappingDesc::SHADOW))" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
883 | CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)))do { __sanitizer::u64 v1 = (__sanitizer::u64)((addr_is_type(( uptr)(((((uptr)((((uptr)((addr))) ^ 0x500000000000ULL))) + 0x100000000000ULL ))), MappingDesc::ORIGIN))); __sanitizer::u64 v2 = (__sanitizer ::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer ::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 883, "(" "(addr_is_type((uptr)(((((uptr)((((uptr)((addr))) ^ 0x500000000000ULL))) + 0x100000000000ULL))), MappingDesc::ORIGIN))" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
884 | CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)))do { __sanitizer::u64 v1 = (__sanitizer::u64)((((((uptr)((((uptr )((addr))) ^ 0x500000000000ULL))) + 0x100000000000ULL)))); __sanitizer ::u64 v2 = (__sanitizer::u64)(((((uptr)((((uptr)(addr)) ^ 0x500000000000ULL ))) + 0x100000000000ULL))); if (__builtin_expect(!!(!(v1 == v2 )), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 884, "(" "(((((uptr)((((uptr)((addr))) ^ 0x500000000000ULL))) + 0x100000000000ULL)))" ") " "==" " (" "((((uptr)((((uptr)(addr)) ^ 0x500000000000ULL))) + 0x100000000000ULL))" ")", v1, v2); } while (false); | ||||
885 | |||||
886 | addr = end - 1; | ||||
887 | CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)))do { __sanitizer::u64 v1 = (__sanitizer::u64)((addr_is_type(( uptr)((((uptr)(addr)) ^ 0x500000000000ULL)), MappingDesc::SHADOW ))); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 887, "(" "(addr_is_type((uptr)((((uptr)(addr)) ^ 0x500000000000ULL)), MappingDesc::SHADOW))" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
888 | CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)))do { __sanitizer::u64 v1 = (__sanitizer::u64)((addr_is_type(( uptr)(((((uptr)((((uptr)((addr))) ^ 0x500000000000ULL))) + 0x100000000000ULL ))), MappingDesc::ORIGIN))); __sanitizer::u64 v2 = (__sanitizer ::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer ::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 888, "(" "(addr_is_type((uptr)(((((uptr)((((uptr)((addr))) ^ 0x500000000000ULL))) + 0x100000000000ULL))), MappingDesc::ORIGIN))" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
889 | CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)))do { __sanitizer::u64 v1 = (__sanitizer::u64)((((((uptr)((((uptr )((addr))) ^ 0x500000000000ULL))) + 0x100000000000ULL)))); __sanitizer ::u64 v2 = (__sanitizer::u64)(((((uptr)((((uptr)(addr)) ^ 0x500000000000ULL ))) + 0x100000000000ULL))); if (__builtin_expect(!!(!(v1 == v2 )), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 889, "(" "(((((uptr)((((uptr)((addr))) ^ 0x500000000000ULL))) + 0x100000000000ULL)))" ") " "==" " (" "((((uptr)((((uptr)(addr)) ^ 0x500000000000ULL))) + 0x100000000000ULL))" ")", v1, v2); } while (false); | ||||
890 | } | ||||
891 | prev_end = end; | ||||
892 | } | ||||
893 | } | ||||
894 | |||||
895 | // TODO: CheckMemoryRangeAvailability is based on msan. | ||||
896 | // Consider refactoring these into a shared implementation. | ||||
897 | static bool CheckMemoryRangeAvailability(uptr beg, uptr size) { | ||||
898 | if (size > 0) { | ||||
899 | uptr end = beg + size - 1; | ||||
900 | if (!MemoryRangeIsAvailable(beg, end)) { | ||||
901 | Printf("FATAL: Memory range %p - %p is not available.\n", beg, end); | ||||
902 | return false; | ||||
903 | } | ||||
904 | } | ||||
905 | return true; | ||||
906 | } | ||||
907 | |||||
908 | // TODO: ProtectMemoryRange is based on msan. | ||||
909 | // Consider refactoring these into a shared implementation. | ||||
910 | static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) { | ||||
911 | if (size > 0) { | ||||
912 | void *addr = MmapFixedNoAccess(beg, size, name); | ||||
913 | if (beg == 0 && addr) { | ||||
914 | // Depending on the kernel configuration, we may not be able to protect | ||||
915 | // the page at address zero. | ||||
916 | uptr gap = 16 * GetPageSizeCached(); | ||||
917 | beg += gap; | ||||
918 | size -= gap; | ||||
919 | addr = MmapFixedNoAccess(beg, size, name); | ||||
920 | } | ||||
921 | if ((uptr)addr != beg) { | ||||
922 | uptr end = beg + size - 1; | ||||
923 | Printf("FATAL: Cannot protect memory range %p - %p (%s).\n", beg, end, | ||||
924 | name); | ||||
925 | return false; | ||||
926 | } | ||||
927 | } | ||||
928 | return true; | ||||
929 | } | ||||
930 | |||||
931 | // TODO: InitShadow is based on msan. | ||||
932 | // Consider refactoring these into a shared implementation. | ||||
933 | bool InitShadow(bool init_origins) { | ||||
934 | // Let user know mapping parameters first. | ||||
935 | VPrintf(1, "dfsan_init %p\n", &__dfsan::dfsan_init)do { if ((uptr)Verbosity() >= (1)) Printf("dfsan_init %p\n" , &__dfsan::dfsan_init); } while (0); | ||||
936 | for (unsigned i = 0; i < kMemoryLayoutSize; ++i) | ||||
937 | VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start,do { if ((uptr)Verbosity() >= (1)) Printf("%s: %zx - %zx\n" , kMemoryLayout[i].name, kMemoryLayout[i].start, kMemoryLayout [i].end - 1); } while (0) | ||||
938 | kMemoryLayout[i].end - 1)do { if ((uptr)Verbosity() >= (1)) Printf("%s: %zx - %zx\n" , kMemoryLayout[i].name, kMemoryLayout[i].start, kMemoryLayout [i].end - 1); } while (0); | ||||
939 | |||||
940 | CheckMemoryLayoutSanity(); | ||||
941 | |||||
942 | if (!MEM_IS_APP(&__dfsan::dfsan_init)addr_is_type((uptr)(&__dfsan::dfsan_init), MappingDesc::APP )) { | ||||
943 | Printf("FATAL: Code %p is out of application range. Non-PIE build?\n", | ||||
944 | (uptr)&__dfsan::dfsan_init); | ||||
945 | return false; | ||||
946 | } | ||||
947 | |||||
948 | const uptr maxVirtualAddress = GetMaxUserVirtualAddress(); | ||||
949 | |||||
950 | for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { | ||||
951 | uptr start = kMemoryLayout[i].start; | ||||
952 | uptr end = kMemoryLayout[i].end; | ||||
953 | uptr size = end - start; | ||||
954 | MappingDesc::Type type = kMemoryLayout[i].type; | ||||
955 | |||||
956 | // Check if the segment should be mapped based on platform constraints. | ||||
957 | if (start >= maxVirtualAddress) | ||||
958 | continue; | ||||
959 | |||||
960 | bool map = type == MappingDesc::SHADOW || | ||||
961 | (init_origins && type == MappingDesc::ORIGIN); | ||||
962 | bool protect = type == MappingDesc::INVALID || | ||||
963 | (!init_origins && type == MappingDesc::ORIGIN); | ||||
964 | CHECK(!(map && protect))do { __sanitizer::u64 v1 = (__sanitizer::u64)((!(map && protect))); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if ( __builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 964, "(" "(!(map && protect))" ") " "!=" " (" "0" ")" , v1, v2); } while (false); | ||||
965 | if (!map && !protect) | ||||
966 | CHECK(type == MappingDesc::APP)do { __sanitizer::u64 v1 = (__sanitizer::u64)((type == MappingDesc ::APP)); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 966, "(" "(type == MappingDesc::APP)" ") " "!=" " (" "0" ")" , v1, v2); } while (false); | ||||
967 | if (map) { | ||||
968 | if (!CheckMemoryRangeAvailability(start, size)) | ||||
969 | return false; | ||||
970 | if (!MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name)) | ||||
971 | return false; | ||||
972 | if (common_flags()->use_madv_dontdump) | ||||
973 | DontDumpShadowMemory(start, size); | ||||
974 | } | ||||
975 | if (protect) { | ||||
976 | if (!CheckMemoryRangeAvailability(start, size)) | ||||
977 | return false; | ||||
978 | if (!ProtectMemoryRange(start, size, kMemoryLayout[i].name)) | ||||
979 | return false; | ||||
980 | } | ||||
981 | } | ||||
982 | |||||
983 | return true; | ||||
984 | } | ||||
985 | |||||
986 | static void DFsanInit(int argc, char **argv, char **envp) { | ||||
987 | CHECK(!dfsan_init_is_running)do { __sanitizer::u64 v1 = (__sanitizer::u64)((!dfsan_init_is_running )); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/dfsan.cpp" , 987, "(" "(!dfsan_init_is_running)" ") " "!=" " (" "0" ")", v1, v2); } while (false); | ||||
988 | if (dfsan_inited) | ||||
989 | return; | ||||
990 | dfsan_init_is_running = true; | ||||
991 | SanitizerToolName = "DataflowSanitizer"; | ||||
992 | |||||
993 | AvoidCVE_2016_2143(); | ||||
994 | |||||
995 | InitializeFlags(); | ||||
996 | |||||
997 | CheckASLR(); | ||||
998 | |||||
999 | InitShadow(dfsan_get_track_origins()); | ||||
1000 | |||||
1001 | initialize_interceptors(); | ||||
1002 | |||||
1003 | // Set up threads | ||||
1004 | DFsanTSDInit(DFsanTSDDtor); | ||||
1005 | |||||
1006 | dfsan_allocator_init(); | ||||
1007 | |||||
1008 | DFsanThread *main_thread = DFsanThread::Create(nullptr, nullptr, nullptr); | ||||
1009 | SetCurrentThread(main_thread); | ||||
1010 | main_thread->ThreadStart(); | ||||
1011 | |||||
1012 | dfsan_init_is_running = false; | ||||
1013 | dfsan_inited = true; | ||||
1014 | } | ||||
1015 | |||||
1016 | namespace __dfsan { | ||||
1017 | |||||
1018 | void dfsan_init() { DFsanInit(0, nullptr, nullptr); } | ||||
1019 | |||||
1020 | } // namespace __dfsan | ||||
1021 | |||||
1022 | #if SANITIZER_CAN_USE_PREINIT_ARRAY1 | ||||
1023 | __attribute__((section(".preinit_array"), | ||||
1024 | used)) static void (*dfsan_init_ptr)(int, char **, | ||||
1025 | char **) = DFsanInit; | ||||
1026 | #endif |
1 | //===-- dfsan_origin.h ----------------------------------*- C++ -*-===// | |||
2 | // | |||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |||
4 | // See https://llvm.org/LICENSE.txt for license information. | |||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | // | |||
9 | // This file is a part of DataFlowSanitizer. | |||
10 | // | |||
11 | // Origin id utils. | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | #ifndef DFSAN_ORIGIN_H | |||
15 | #define DFSAN_ORIGIN_H | |||
16 | ||||
17 | #include "dfsan_chained_origin_depot.h" | |||
18 | #include "dfsan_flags.h" | |||
19 | #include "sanitizer_common/sanitizer_stackdepot.h" | |||
20 | ||||
21 | namespace __dfsan { | |||
22 | ||||
23 | // Origin handling. | |||
24 | // | |||
25 | // Origin is a 32-bit identifier that is attached to any taint value in the | |||
26 | // program and describes how this memory came to be tainted. | |||
27 | // | |||
28 | // Chained origin id is like: | |||
29 | // zzzz xxxx xxxx xxxx | |||
30 | // | |||
31 | // Chained origin id describes an event of storing a taint value to | |||
32 | // memory. The xxx part is a value of ChainedOriginDepot, which is a mapping of | |||
33 | // (stack_id, prev_id) -> id, where | |||
34 | // * stack_id describes the event. | |||
35 | // StackDepot keeps a mapping between those and corresponding stack traces. | |||
36 | // * prev_id is another origin id that describes the earlier part of the | |||
37 | // taint value history. 0 prev_id indicates the start of a chain. | |||
38 | // Following a chain of prev_id provides the full recorded history of a taint | |||
39 | // value. | |||
40 | // | |||
41 | // This, effectively, defines a forest where nodes are points in value history | |||
42 | // marked with origin ids, and edges are events that are marked with stack_id. | |||
43 | // | |||
44 | // The "zzzz" bits of chained origin id are used to store the length of the | |||
45 | // origin chain. | |||
46 | ||||
47 | class Origin { | |||
48 | public: | |||
49 | static bool isValidId(u32 id) { return id != 0; } | |||
50 | ||||
51 | u32 raw_id() const { return raw_id_; } | |||
52 | ||||
53 | bool isChainedOrigin() const { return Origin::isValidId(raw_id_); } | |||
54 | ||||
55 | u32 getChainedId() const { | |||
56 | CHECK(Origin::isValidId(raw_id_))do { __sanitizer::u64 v1 = (__sanitizer::u64)((Origin::isValidId (raw_id_))); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if ( __builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/../dfsan/dfsan_origin.h" , 56, "(" "(Origin::isValidId(raw_id_))" ") " "!=" " (" "0" ")" , v1, v2); } while (false); | |||
57 | return raw_id_ & kChainedIdMask; | |||
58 | } | |||
59 | ||||
60 | // Returns the next origin in the chain and the current stack trace. | |||
61 | // | |||
62 | // It scans a partition of StackDepot linearly, and is used only by origin | |||
63 | // tracking report. | |||
64 | Origin getNextChainedOrigin(StackTrace *stack) const { | |||
65 | CHECK(Origin::isValidId(raw_id_))do { __sanitizer::u64 v1 = (__sanitizer::u64)((Origin::isValidId (raw_id_))); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if ( __builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/../dfsan/dfsan_origin.h" , 65, "(" "(Origin::isValidId(raw_id_))" ") " "!=" " (" "0" ")" , v1, v2); } while (false); | |||
66 | u32 prev_id; | |||
67 | u32 stack_id = GetChainedOriginDepot()->Get(getChainedId(), &prev_id); | |||
68 | if (stack) | |||
69 | *stack = StackDepotGet(stack_id); | |||
70 | return Origin(prev_id); | |||
71 | } | |||
72 | ||||
73 | static Origin CreateChainedOrigin(Origin prev, StackTrace *stack) { | |||
74 | int depth = prev.isChainedOrigin() ? prev.depth() : -1; | |||
75 | // depth is the length of the chain minus 1. | |||
76 | // origin_history_size of 0 means unlimited depth. | |||
77 | if (flags().origin_history_size > 0) { | |||
78 | ++depth; | |||
79 | if (depth >= flags().origin_history_size || depth > kMaxDepth) | |||
80 | return prev; | |||
81 | } | |||
82 | ||||
83 | StackDepotHandle h = StackDepotPut_WithHandle(*stack); | |||
84 | if (!h.valid()) | |||
85 | return prev; | |||
86 | ||||
87 | if (flags().origin_history_per_stack_limit > 0) { | |||
88 | int use_count = h.use_count(); | |||
89 | if (use_count > flags().origin_history_per_stack_limit) | |||
90 | return prev; | |||
91 | } | |||
92 | ||||
93 | u32 chained_id; | |||
94 | bool inserted = | |||
95 | GetChainedOriginDepot()->Put(h.id(), prev.raw_id(), &chained_id); | |||
96 | CHECK((chained_id & kChainedIdMask) == chained_id)do { __sanitizer::u64 v1 = (__sanitizer::u64)(((chained_id & kChainedIdMask) == chained_id)); __sanitizer::u64 v2 = (__sanitizer ::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer ::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/../dfsan/dfsan_origin.h" , 96, "(" "((chained_id & kChainedIdMask) == chained_id)" ") " "!=" " (" "0" ")", v1, v2); } while (false); | |||
97 | ||||
98 | if (inserted && flags().origin_history_per_stack_limit > 0) | |||
99 | h.inc_use_count_unsafe(); | |||
100 | ||||
101 | return Origin((depth << kDepthShift) | chained_id); | |||
| ||||
102 | } | |||
103 | ||||
104 | static Origin FromRawId(u32 id) { return Origin(id); } | |||
105 | ||||
106 | private: | |||
107 | static const int kDepthBits = 4; | |||
108 | static const int kDepthShift = 32 - kDepthBits; | |||
109 | ||||
110 | static const u32 kChainedIdMask = ((u32)-1) >> kDepthBits; | |||
111 | ||||
112 | u32 raw_id_; | |||
113 | ||||
114 | explicit Origin(u32 raw_id) : raw_id_(raw_id) {} | |||
115 | ||||
116 | int depth() const { | |||
117 | CHECK(isChainedOrigin())do { __sanitizer::u64 v1 = (__sanitizer::u64)((isChainedOrigin ())); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/compiler-rt/lib/dfsan/../dfsan/dfsan_origin.h" , 117, "(" "(isChainedOrigin())" ") " "!=" " (" "0" ")", v1, v2 ); } while (false); | |||
118 | return (raw_id_ >> kDepthShift) & ((1 << kDepthBits) - 1); | |||
119 | } | |||
120 | ||||
121 | public: | |||
122 | static const int kMaxDepth = (1 << kDepthBits) - 1; | |||
123 | }; | |||
124 | ||||
125 | } // namespace __dfsan | |||
126 | ||||
127 | #endif // DFSAN_ORIGIN_H |