xref: /openbsd-src/gnu/llvm/compiler-rt/lib/dfsan/dfsan.cpp (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===-- dfsan.cpp ---------------------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of DataFlowSanitizer.
103cab2bb3Spatrick //
113cab2bb3Spatrick // DataFlowSanitizer runtime.  This file defines the public interface to
123cab2bb3Spatrick // DataFlowSanitizer as well as the definition of certain runtime functions
133cab2bb3Spatrick // called automatically by the compiler (specifically the instrumentation pass
143cab2bb3Spatrick // in llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp).
153cab2bb3Spatrick //
163cab2bb3Spatrick // The public interface is defined in include/sanitizer/dfsan_interface.h whose
173cab2bb3Spatrick // functions are prefixed dfsan_ while the compiler interface functions are
183cab2bb3Spatrick // prefixed __dfsan_.
193cab2bb3Spatrick //===----------------------------------------------------------------------===//
203cab2bb3Spatrick 
21d89ec533Spatrick #include "dfsan/dfsan.h"
22d89ec533Spatrick 
23d89ec533Spatrick #include "dfsan/dfsan_chained_origin_depot.h"
24d89ec533Spatrick #include "dfsan/dfsan_flags.h"
25d89ec533Spatrick #include "dfsan/dfsan_origin.h"
26d89ec533Spatrick #include "dfsan/dfsan_thread.h"
273cab2bb3Spatrick #include "sanitizer_common/sanitizer_atomic.h"
283cab2bb3Spatrick #include "sanitizer_common/sanitizer_common.h"
293cab2bb3Spatrick #include "sanitizer_common/sanitizer_file.h"
303cab2bb3Spatrick #include "sanitizer_common/sanitizer_flag_parser.h"
31d89ec533Spatrick #include "sanitizer_common/sanitizer_flags.h"
32d89ec533Spatrick #include "sanitizer_common/sanitizer_internal_defs.h"
333cab2bb3Spatrick #include "sanitizer_common/sanitizer_libc.h"
34d89ec533Spatrick #include "sanitizer_common/sanitizer_report_decorator.h"
35d89ec533Spatrick #include "sanitizer_common/sanitizer_stacktrace.h"
363cab2bb3Spatrick 
373cab2bb3Spatrick using namespace __dfsan;
383cab2bb3Spatrick 
393cab2bb3Spatrick Flags __dfsan::flags_data;
403cab2bb3Spatrick 
41d89ec533Spatrick // The size of TLS variables. These constants must be kept in sync with the ones
42d89ec533Spatrick // in DataFlowSanitizer.cpp.
43d89ec533Spatrick static const int kDFsanArgTlsSize = 800;
44d89ec533Spatrick static const int kDFsanRetvalTlsSize = 800;
45d89ec533Spatrick static const int kDFsanArgOriginTlsSize = 800;
463cab2bb3Spatrick 
47d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u64
48d89ec533Spatrick     __dfsan_retval_tls[kDFsanRetvalTlsSize / sizeof(u64)];
49d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u32 __dfsan_retval_origin_tls;
50d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u64
51d89ec533Spatrick     __dfsan_arg_tls[kDFsanArgTlsSize / sizeof(u64)];
52d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u32
53d89ec533Spatrick     __dfsan_arg_origin_tls[kDFsanArgOriginTlsSize / sizeof(u32)];
54d89ec533Spatrick 
55d89ec533Spatrick // Instrumented code may set this value in terms of -dfsan-track-origins.
56d89ec533Spatrick // * undefined or 0: do not track origins.
57d89ec533Spatrick // * 1: track origins at memory store operations.
58d89ec533Spatrick // * 2: track origins at memory load and store operations.
59d89ec533Spatrick //      TODO: track callsites.
60d89ec533Spatrick extern "C" SANITIZER_WEAK_ATTRIBUTE const int __dfsan_track_origins;
61d89ec533Spatrick 
dfsan_get_track_origins()62d89ec533Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE int dfsan_get_track_origins() {
63d89ec533Spatrick   return &__dfsan_track_origins ? __dfsan_track_origins : 0;
64d89ec533Spatrick }
653cab2bb3Spatrick 
663cab2bb3Spatrick // On Linux/x86_64, memory is laid out as follows:
673cab2bb3Spatrick //
683cab2bb3Spatrick //  +--------------------+ 0x800000000000 (top of memory)
69d89ec533Spatrick //  |    application 3   |
70d89ec533Spatrick //  +--------------------+ 0x700000000000
71d89ec533Spatrick //  |      invalid       |
72d89ec533Spatrick //  +--------------------+ 0x610000000000
73d89ec533Spatrick //  |      origin 1      |
74d89ec533Spatrick //  +--------------------+ 0x600000000000
75d89ec533Spatrick //  |    application 2   |
76d89ec533Spatrick //  +--------------------+ 0x510000000000
77d89ec533Spatrick //  |      shadow 1      |
78d89ec533Spatrick //  +--------------------+ 0x500000000000
79d89ec533Spatrick //  |      invalid       |
80d89ec533Spatrick //  +--------------------+ 0x400000000000
81d89ec533Spatrick //  |      origin 3      |
82d89ec533Spatrick //  +--------------------+ 0x300000000000
83d89ec533Spatrick //  |      shadow 3      |
84d89ec533Spatrick //  +--------------------+ 0x200000000000
85d89ec533Spatrick //  |      origin 2      |
86d89ec533Spatrick //  +--------------------+ 0x110000000000
87d89ec533Spatrick //  |      invalid       |
88d89ec533Spatrick //  +--------------------+ 0x100000000000
89d89ec533Spatrick //  |      shadow 2      |
90d89ec533Spatrick //  +--------------------+ 0x010000000000
91d89ec533Spatrick //  |    application 1   |
923cab2bb3Spatrick //  +--------------------+ 0x000000000000
933cab2bb3Spatrick //
94d89ec533Spatrick //  MEM_TO_SHADOW(mem) = mem ^ 0x500000000000
95d89ec533Spatrick //  SHADOW_TO_ORIGIN(shadow) = shadow + 0x100000000000
963cab2bb3Spatrick 
973cab2bb3Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE
__dfsan_union_load(const dfsan_label * ls,uptr n)983cab2bb3Spatrick dfsan_label __dfsan_union_load(const dfsan_label *ls, uptr n) {
993cab2bb3Spatrick   dfsan_label label = ls[0];
100d89ec533Spatrick   for (uptr i = 1; i != n; ++i)
101d89ec533Spatrick     label |= ls[i];
1023cab2bb3Spatrick   return label;
1033cab2bb3Spatrick }
1043cab2bb3Spatrick 
105d89ec533Spatrick // Return the union of all the n labels from addr at the high 32 bit, and the
106d89ec533Spatrick // origin of the first taint byte at the low 32 bit.
107d89ec533Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE u64
__dfsan_load_label_and_origin(const void * addr,uptr n)108d89ec533Spatrick __dfsan_load_label_and_origin(const void *addr, uptr n) {
109d89ec533Spatrick   dfsan_label label = 0;
110d89ec533Spatrick   u64 ret = 0;
111d89ec533Spatrick   uptr p = (uptr)addr;
112d89ec533Spatrick   dfsan_label *s = shadow_for((void *)p);
113d89ec533Spatrick   for (uptr i = 0; i < n; ++i) {
114d89ec533Spatrick     dfsan_label l = s[i];
115d89ec533Spatrick     if (!l)
116d89ec533Spatrick       continue;
117d89ec533Spatrick     label |= l;
118d89ec533Spatrick     if (!ret)
119d89ec533Spatrick       ret = *(dfsan_origin *)origin_for((void *)(p + i));
120d89ec533Spatrick   }
121d89ec533Spatrick   return ret | (u64)label << 32;
122d89ec533Spatrick }
123d89ec533Spatrick 
1243cab2bb3Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE
__dfsan_unimplemented(char * fname)1253cab2bb3Spatrick void __dfsan_unimplemented(char *fname) {
1263cab2bb3Spatrick   if (flags().warn_unimplemented)
1273cab2bb3Spatrick     Report("WARNING: DataFlowSanitizer: call to uninstrumented function %s\n",
1283cab2bb3Spatrick            fname);
1293cab2bb3Spatrick }
1303cab2bb3Spatrick 
__dfsan_wrapper_extern_weak_null(const void * addr,char * fname)131*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_wrapper_extern_weak_null(
132*810390e3Srobert     const void *addr, char *fname) {
133*810390e3Srobert   if (!addr)
134*810390e3Srobert     Report(
135*810390e3Srobert         "ERROR: DataFlowSanitizer: dfsan generated wrapper calling null "
136*810390e3Srobert         "extern_weak function %s\nIf this only happens with dfsan, the "
137*810390e3Srobert         "dfsan instrumentation pass may be accidentally optimizing out a "
138*810390e3Srobert         "null check\n",
139*810390e3Srobert         fname);
140*810390e3Srobert }
141*810390e3Srobert 
1423cab2bb3Spatrick // Use '-mllvm -dfsan-debug-nonzero-labels' and break on this function
1433cab2bb3Spatrick // to try to figure out where labels are being introduced in a nominally
1443cab2bb3Spatrick // label-free program.
__dfsan_nonzero_label()1453cab2bb3Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_nonzero_label() {
1463cab2bb3Spatrick   if (flags().warn_nonzero_labels)
1473cab2bb3Spatrick     Report("WARNING: DataFlowSanitizer: saw nonzero label\n");
1483cab2bb3Spatrick }
1493cab2bb3Spatrick 
1503cab2bb3Spatrick // Indirect call to an uninstrumented vararg function. We don't have a way of
1513cab2bb3Spatrick // handling these at the moment.
1523cab2bb3Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__dfsan_vararg_wrapper(const char * fname)1533cab2bb3Spatrick __dfsan_vararg_wrapper(const char *fname) {
1543cab2bb3Spatrick   Report("FATAL: DataFlowSanitizer: unsupported indirect call to vararg "
1553cab2bb3Spatrick          "function %s\n", fname);
1563cab2bb3Spatrick   Die();
1573cab2bb3Spatrick }
1583cab2bb3Spatrick 
159d89ec533Spatrick // Resolves the union of two labels.
1603cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
dfsan_union(dfsan_label l1,dfsan_label l2)1613cab2bb3Spatrick dfsan_union(dfsan_label l1, dfsan_label l2) {
162d89ec533Spatrick   return l1 | l2;
1633cab2bb3Spatrick }
1643cab2bb3Spatrick 
165d89ec533Spatrick static const uptr kOriginAlign = sizeof(dfsan_origin);
166d89ec533Spatrick static const uptr kOriginAlignMask = ~(kOriginAlign - 1UL);
167d89ec533Spatrick 
OriginAlignUp(uptr u)168d89ec533Spatrick static uptr OriginAlignUp(uptr u) {
169d89ec533Spatrick   return (u + kOriginAlign - 1) & kOriginAlignMask;
1703cab2bb3Spatrick }
1713cab2bb3Spatrick 
OriginAlignDown(uptr u)172d89ec533Spatrick static uptr OriginAlignDown(uptr u) { return u & kOriginAlignMask; }
173d89ec533Spatrick 
174d89ec533Spatrick // Return the origin of the first taint byte in the size bytes from the address
175d89ec533Spatrick // addr.
GetOriginIfTainted(uptr addr,uptr size)176d89ec533Spatrick static dfsan_origin GetOriginIfTainted(uptr addr, uptr size) {
177d89ec533Spatrick   for (uptr i = 0; i < size; ++i, ++addr) {
178d89ec533Spatrick     dfsan_label *s = shadow_for((void *)addr);
179d89ec533Spatrick 
180d89ec533Spatrick     if (*s) {
181d89ec533Spatrick       // Validate address region.
182d89ec533Spatrick       CHECK(MEM_IS_SHADOW(s));
183d89ec533Spatrick       return *(dfsan_origin *)origin_for((void *)addr);
184d89ec533Spatrick     }
185d89ec533Spatrick   }
186d89ec533Spatrick   return 0;
187d89ec533Spatrick }
188d89ec533Spatrick 
189d89ec533Spatrick // For platforms which support slow unwinder only, we need to restrict the store
190d89ec533Spatrick // context size to 1, basically only storing the current pc, because the slow
191d89ec533Spatrick // unwinder which is based on libunwind is not async signal safe and causes
192d89ec533Spatrick // random freezes in forking applications as well as in signal handlers.
193d89ec533Spatrick // DFSan supports only Linux. So we do not restrict the store context size.
194d89ec533Spatrick #define GET_STORE_STACK_TRACE_PC_BP(pc, bp) \
195d89ec533Spatrick   BufferedStackTrace stack;                 \
196d89ec533Spatrick   stack.Unwind(pc, bp, nullptr, true, flags().store_context_size);
197d89ec533Spatrick 
198d89ec533Spatrick #define PRINT_CALLER_STACK_TRACE        \
199d89ec533Spatrick   {                                     \
200d89ec533Spatrick     GET_CALLER_PC_BP_SP;                \
201d89ec533Spatrick     (void)sp;                           \
202d89ec533Spatrick     GET_STORE_STACK_TRACE_PC_BP(pc, bp) \
203d89ec533Spatrick     stack.Print();                      \
204d89ec533Spatrick   }
205d89ec533Spatrick 
206d89ec533Spatrick // Return a chain with the previous ID id and the current stack.
207d89ec533Spatrick // from_init = true if this is the first chain of an origin tracking path.
ChainOrigin(u32 id,StackTrace * stack,bool from_init=false)208d89ec533Spatrick static u32 ChainOrigin(u32 id, StackTrace *stack, bool from_init = false) {
209d89ec533Spatrick   // StackDepot is not async signal safe. Do not create new chains in a signal
210d89ec533Spatrick   // handler.
211d89ec533Spatrick   DFsanThread *t = GetCurrentThread();
212d89ec533Spatrick   if (t && t->InSignalHandler())
213d89ec533Spatrick     return id;
214d89ec533Spatrick 
215d89ec533Spatrick   // As an optimization the origin of an application byte is updated only when
216d89ec533Spatrick   // its shadow is non-zero. Because we are only interested in the origins of
217d89ec533Spatrick   // taint labels, it does not matter what origin a zero label has. This reduces
218d89ec533Spatrick   // memory write cost. MSan does similar optimization. The following invariant
219d89ec533Spatrick   // may not hold because of some bugs. We check the invariant to help debug.
220d89ec533Spatrick   if (!from_init && id == 0 && flags().check_origin_invariant) {
221d89ec533Spatrick     Printf("  DFSan found invalid origin invariant\n");
222d89ec533Spatrick     PRINT_CALLER_STACK_TRACE
223d89ec533Spatrick   }
224d89ec533Spatrick 
225d89ec533Spatrick   Origin o = Origin::FromRawId(id);
226d89ec533Spatrick   stack->tag = StackTrace::TAG_UNKNOWN;
227d89ec533Spatrick   Origin chained = Origin::CreateChainedOrigin(o, stack);
228d89ec533Spatrick   return chained.raw_id();
229d89ec533Spatrick }
230d89ec533Spatrick 
ChainAndWriteOriginIfTainted(uptr src,uptr size,uptr dst,StackTrace * stack)231d89ec533Spatrick static void ChainAndWriteOriginIfTainted(uptr src, uptr size, uptr dst,
232d89ec533Spatrick                                          StackTrace *stack) {
233d89ec533Spatrick   dfsan_origin o = GetOriginIfTainted(src, size);
234d89ec533Spatrick   if (o) {
235d89ec533Spatrick     o = ChainOrigin(o, stack);
236d89ec533Spatrick     *(dfsan_origin *)origin_for((void *)dst) = o;
237d89ec533Spatrick   }
238d89ec533Spatrick }
239d89ec533Spatrick 
240d89ec533Spatrick // Copy the origins of the size bytes from src to dst. The source and target
241d89ec533Spatrick // memory ranges cannot be overlapped. This is used by memcpy. stack records the
242d89ec533Spatrick // stack trace of the memcpy. When dst and src are not 4-byte aligned properly,
243d89ec533Spatrick // origins at the unaligned address boundaries may be overwritten because four
244d89ec533Spatrick // contiguous bytes share the same origin.
CopyOrigin(const void * dst,const void * src,uptr size,StackTrace * stack)245d89ec533Spatrick static void CopyOrigin(const void *dst, const void *src, uptr size,
246d89ec533Spatrick                        StackTrace *stack) {
247d89ec533Spatrick   uptr d = (uptr)dst;
248d89ec533Spatrick   uptr beg = OriginAlignDown(d);
249d89ec533Spatrick   // Copy left unaligned origin if that memory is tainted.
250d89ec533Spatrick   if (beg < d) {
251d89ec533Spatrick     ChainAndWriteOriginIfTainted((uptr)src, beg + kOriginAlign - d, beg, stack);
252d89ec533Spatrick     beg += kOriginAlign;
253d89ec533Spatrick   }
254d89ec533Spatrick 
255d89ec533Spatrick   uptr end = OriginAlignDown(d + size);
256d89ec533Spatrick   // If both ends fall into the same 4-byte slot, we are done.
257d89ec533Spatrick   if (end < beg)
258d89ec533Spatrick     return;
259d89ec533Spatrick 
260d89ec533Spatrick   // Copy right unaligned origin if that memory is tainted.
261d89ec533Spatrick   if (end < d + size)
262d89ec533Spatrick     ChainAndWriteOriginIfTainted((uptr)src + (end - d), (d + size) - end, end,
263d89ec533Spatrick                                  stack);
264d89ec533Spatrick 
265d89ec533Spatrick   if (beg >= end)
266d89ec533Spatrick     return;
267d89ec533Spatrick 
268d89ec533Spatrick   // Align src up.
269d89ec533Spatrick   uptr src_a = OriginAlignUp((uptr)src);
270d89ec533Spatrick   dfsan_origin *src_o = origin_for((void *)src_a);
271d89ec533Spatrick   u32 *src_s = (u32 *)shadow_for((void *)src_a);
272d89ec533Spatrick   dfsan_origin *src_end = origin_for((void *)(src_a + (end - beg)));
273d89ec533Spatrick   dfsan_origin *dst_o = origin_for((void *)beg);
274d89ec533Spatrick   dfsan_origin last_src_o = 0;
275d89ec533Spatrick   dfsan_origin last_dst_o = 0;
276d89ec533Spatrick   for (; src_o < src_end; ++src_o, ++src_s, ++dst_o) {
277d89ec533Spatrick     if (!*src_s)
278d89ec533Spatrick       continue;
279d89ec533Spatrick     if (*src_o != last_src_o) {
280d89ec533Spatrick       last_src_o = *src_o;
281d89ec533Spatrick       last_dst_o = ChainOrigin(last_src_o, stack);
282d89ec533Spatrick     }
283d89ec533Spatrick     *dst_o = last_dst_o;
284d89ec533Spatrick   }
285d89ec533Spatrick }
286d89ec533Spatrick 
287d89ec533Spatrick // Copy the origins of the size bytes from src to dst. The source and target
288d89ec533Spatrick // memory ranges may be overlapped. So the copy is done in a reverse order.
289d89ec533Spatrick // This is used by memmove. stack records the stack trace of the memmove.
ReverseCopyOrigin(const void * dst,const void * src,uptr size,StackTrace * stack)290d89ec533Spatrick static void ReverseCopyOrigin(const void *dst, const void *src, uptr size,
291d89ec533Spatrick                               StackTrace *stack) {
292d89ec533Spatrick   uptr d = (uptr)dst;
293d89ec533Spatrick   uptr end = OriginAlignDown(d + size);
294d89ec533Spatrick 
295d89ec533Spatrick   // Copy right unaligned origin if that memory is tainted.
296d89ec533Spatrick   if (end < d + size)
297d89ec533Spatrick     ChainAndWriteOriginIfTainted((uptr)src + (end - d), (d + size) - end, end,
298d89ec533Spatrick                                  stack);
299d89ec533Spatrick 
300d89ec533Spatrick   uptr beg = OriginAlignDown(d);
301d89ec533Spatrick 
302d89ec533Spatrick   if (beg + kOriginAlign < end) {
303d89ec533Spatrick     // Align src up.
304d89ec533Spatrick     uptr src_a = OriginAlignUp((uptr)src);
305d89ec533Spatrick     void *src_end = (void *)(src_a + end - beg - kOriginAlign);
306d89ec533Spatrick     dfsan_origin *src_end_o = origin_for(src_end);
307d89ec533Spatrick     u32 *src_end_s = (u32 *)shadow_for(src_end);
308d89ec533Spatrick     dfsan_origin *src_begin_o = origin_for((void *)src_a);
309d89ec533Spatrick     dfsan_origin *dst = origin_for((void *)(end - kOriginAlign));
310d89ec533Spatrick     dfsan_origin last_src_o = 0;
311d89ec533Spatrick     dfsan_origin last_dst_o = 0;
312d89ec533Spatrick     for (; src_end_o >= src_begin_o; --src_end_o, --src_end_s, --dst) {
313d89ec533Spatrick       if (!*src_end_s)
314d89ec533Spatrick         continue;
315d89ec533Spatrick       if (*src_end_o != last_src_o) {
316d89ec533Spatrick         last_src_o = *src_end_o;
317d89ec533Spatrick         last_dst_o = ChainOrigin(last_src_o, stack);
318d89ec533Spatrick       }
319d89ec533Spatrick       *dst = last_dst_o;
320d89ec533Spatrick     }
321d89ec533Spatrick   }
322d89ec533Spatrick 
323d89ec533Spatrick   // Copy left unaligned origin if that memory is tainted.
324d89ec533Spatrick   if (beg < d)
325d89ec533Spatrick     ChainAndWriteOriginIfTainted((uptr)src, beg + kOriginAlign - d, beg, stack);
326d89ec533Spatrick }
327d89ec533Spatrick 
328d89ec533Spatrick // Copy or move the origins of the len bytes from src to dst. The source and
329d89ec533Spatrick // target memory ranges may or may not be overlapped. This is used by memory
330d89ec533Spatrick // transfer operations. stack records the stack trace of the memory transfer
331d89ec533Spatrick // operation.
MoveOrigin(const void * dst,const void * src,uptr size,StackTrace * stack)332d89ec533Spatrick static void MoveOrigin(const void *dst, const void *src, uptr size,
333d89ec533Spatrick                        StackTrace *stack) {
334d89ec533Spatrick   // Validate address regions.
335d89ec533Spatrick   if (!MEM_IS_SHADOW(shadow_for(dst)) ||
336d89ec533Spatrick       !MEM_IS_SHADOW(shadow_for((void *)((uptr)dst + size))) ||
337d89ec533Spatrick       !MEM_IS_SHADOW(shadow_for(src)) ||
338d89ec533Spatrick       !MEM_IS_SHADOW(shadow_for((void *)((uptr)src + size)))) {
339d89ec533Spatrick     CHECK(false);
340d89ec533Spatrick     return;
341d89ec533Spatrick   }
342d89ec533Spatrick   // If destination origin range overlaps with source origin range, move
343d89ec533Spatrick   // origins by copying origins in a reverse order; otherwise, copy origins in
344d89ec533Spatrick   // a normal order. The orders of origin transfer are consistent with the
345d89ec533Spatrick   // orders of how memcpy and memmove transfer user data.
346*810390e3Srobert   uptr src_aligned_beg = OriginAlignDown((uptr)src);
347*810390e3Srobert   uptr src_aligned_end = OriginAlignDown((uptr)src + size);
348*810390e3Srobert   uptr dst_aligned_beg = OriginAlignDown((uptr)dst);
349d89ec533Spatrick   if (dst_aligned_beg < src_aligned_end && dst_aligned_beg >= src_aligned_beg)
350d89ec533Spatrick     return ReverseCopyOrigin(dst, src, size, stack);
351d89ec533Spatrick   return CopyOrigin(dst, src, size, stack);
352d89ec533Spatrick }
353d89ec533Spatrick 
354d89ec533Spatrick // Set the size bytes from the addres dst to be the origin value.
SetOrigin(const void * dst,uptr size,u32 origin)355d89ec533Spatrick static void SetOrigin(const void *dst, uptr size, u32 origin) {
356d89ec533Spatrick   if (size == 0)
357d89ec533Spatrick     return;
358d89ec533Spatrick 
359d89ec533Spatrick   // Origin mapping is 4 bytes per 4 bytes of application memory.
360d89ec533Spatrick   // Here we extend the range such that its left and right bounds are both
361d89ec533Spatrick   // 4 byte aligned.
362d89ec533Spatrick   uptr x = unaligned_origin_for((uptr)dst);
363d89ec533Spatrick   uptr beg = OriginAlignDown(x);
364d89ec533Spatrick   uptr end = OriginAlignUp(x + size);  // align up.
365d89ec533Spatrick   u64 origin64 = ((u64)origin << 32) | origin;
366d89ec533Spatrick   // This is like memset, but the value is 32-bit. We unroll by 2 to write
367d89ec533Spatrick   // 64 bits at once. May want to unroll further to get 128-bit stores.
368d89ec533Spatrick   if (beg & 7ULL) {
369d89ec533Spatrick     if (*(u32 *)beg != origin)
370d89ec533Spatrick       *(u32 *)beg = origin;
371d89ec533Spatrick     beg += 4;
372d89ec533Spatrick   }
373d89ec533Spatrick   for (uptr addr = beg; addr < (end & ~7UL); addr += 8) {
374d89ec533Spatrick     if (*(u64 *)addr == origin64)
375d89ec533Spatrick       continue;
376d89ec533Spatrick     *(u64 *)addr = origin64;
377d89ec533Spatrick   }
378d89ec533Spatrick   if (end & 7ULL)
379d89ec533Spatrick     if (*(u32 *)(end - kOriginAlign) != origin)
380d89ec533Spatrick       *(u32 *)(end - kOriginAlign) = origin;
381d89ec533Spatrick }
382d89ec533Spatrick 
383d89ec533Spatrick #define RET_CHAIN_ORIGIN(id)           \
384d89ec533Spatrick   GET_CALLER_PC_BP_SP;                 \
385d89ec533Spatrick   (void)sp;                            \
386d89ec533Spatrick   GET_STORE_STACK_TRACE_PC_BP(pc, bp); \
387d89ec533Spatrick   return ChainOrigin(id, &stack);
388d89ec533Spatrick 
389d89ec533Spatrick // Return a new origin chain with the previous ID id and the current stack
390d89ec533Spatrick // trace.
391d89ec533Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
__dfsan_chain_origin(dfsan_origin id)392d89ec533Spatrick __dfsan_chain_origin(dfsan_origin id) {
393d89ec533Spatrick   RET_CHAIN_ORIGIN(id)
394d89ec533Spatrick }
395d89ec533Spatrick 
396d89ec533Spatrick // Return a new origin chain with the previous ID id and the current stack
397d89ec533Spatrick // trace if the label is tainted.
398d89ec533Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
__dfsan_chain_origin_if_tainted(dfsan_label label,dfsan_origin id)399d89ec533Spatrick __dfsan_chain_origin_if_tainted(dfsan_label label, dfsan_origin id) {
400d89ec533Spatrick   if (!label)
401d89ec533Spatrick     return id;
402d89ec533Spatrick   RET_CHAIN_ORIGIN(id)
403d89ec533Spatrick }
404d89ec533Spatrick 
405d89ec533Spatrick // Copy or move the origins of the len bytes from src to dst.
__dfsan_mem_origin_transfer(const void * dst,const void * src,uptr len)406d89ec533Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_mem_origin_transfer(
407d89ec533Spatrick     const void *dst, const void *src, uptr len) {
408d89ec533Spatrick   if (src == dst)
409d89ec533Spatrick     return;
410d89ec533Spatrick   GET_CALLER_PC_BP;
411d89ec533Spatrick   GET_STORE_STACK_TRACE_PC_BP(pc, bp);
412d89ec533Spatrick   MoveOrigin(dst, src, len, &stack);
413d89ec533Spatrick }
414d89ec533Spatrick 
dfsan_mem_origin_transfer(const void * dst,const void * src,uptr len)415*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_mem_origin_transfer(
416*810390e3Srobert     const void *dst, const void *src, uptr len) {
417d89ec533Spatrick   __dfsan_mem_origin_transfer(dst, src, len);
418d89ec533Spatrick }
419d89ec533Spatrick 
CopyShadow(void * dst,const void * src,uptr len)420*810390e3Srobert static void CopyShadow(void *dst, const void *src, uptr len) {
421*810390e3Srobert   internal_memcpy((void *)__dfsan::shadow_for(dst),
422*810390e3Srobert                   (const void *)__dfsan::shadow_for(src),
423*810390e3Srobert                   len * sizeof(dfsan_label));
424*810390e3Srobert }
425*810390e3Srobert 
dfsan_mem_shadow_transfer(void * dst,const void * src,uptr len)426*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_mem_shadow_transfer(
427*810390e3Srobert     void *dst, const void *src, uptr len) {
428*810390e3Srobert   CopyShadow(dst, src, len);
429*810390e3Srobert }
430*810390e3Srobert 
431*810390e3Srobert // Copy shadow and origins of the len bytes from src to dst.
432*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__dfsan_mem_shadow_origin_transfer(void * dst,const void * src,uptr size)433*810390e3Srobert __dfsan_mem_shadow_origin_transfer(void *dst, const void *src, uptr size) {
434*810390e3Srobert   if (src == dst)
435*810390e3Srobert     return;
436*810390e3Srobert   CopyShadow(dst, src, size);
437*810390e3Srobert   if (dfsan_get_track_origins()) {
438*810390e3Srobert     // Duplicating code instead of calling __dfsan_mem_origin_transfer
439*810390e3Srobert     // so that the getting the caller stack frame works correctly.
440*810390e3Srobert     GET_CALLER_PC_BP;
441*810390e3Srobert     GET_STORE_STACK_TRACE_PC_BP(pc, bp);
442*810390e3Srobert     MoveOrigin(dst, src, size, &stack);
443*810390e3Srobert   }
444*810390e3Srobert }
445*810390e3Srobert 
446*810390e3Srobert // Copy shadow and origins as per __atomic_compare_exchange.
447*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__dfsan_mem_shadow_origin_conditional_exchange(u8 condition,void * target,void * expected,const void * desired,uptr size)448*810390e3Srobert __dfsan_mem_shadow_origin_conditional_exchange(u8 condition, void *target,
449*810390e3Srobert                                                void *expected,
450*810390e3Srobert                                                const void *desired, uptr size) {
451*810390e3Srobert   void *dst;
452*810390e3Srobert   const void *src;
453*810390e3Srobert   // condition is result of native call to __atomic_compare_exchange
454*810390e3Srobert   if (condition) {
455*810390e3Srobert     // Copy desired into target
456*810390e3Srobert     dst = target;
457*810390e3Srobert     src = desired;
458*810390e3Srobert   } else {
459*810390e3Srobert     // Copy target into expected
460*810390e3Srobert     dst = expected;
461*810390e3Srobert     src = target;
462*810390e3Srobert   }
463*810390e3Srobert   if (src == dst)
464*810390e3Srobert     return;
465*810390e3Srobert   CopyShadow(dst, src, size);
466*810390e3Srobert   if (dfsan_get_track_origins()) {
467*810390e3Srobert     // Duplicating code instead of calling __dfsan_mem_origin_transfer
468*810390e3Srobert     // so that the getting the caller stack frame works correctly.
469*810390e3Srobert     GET_CALLER_PC_BP;
470*810390e3Srobert     GET_STORE_STACK_TRACE_PC_BP(pc, bp);
471*810390e3Srobert     MoveOrigin(dst, src, size, &stack);
472*810390e3Srobert   }
473*810390e3Srobert }
474*810390e3Srobert 
475d89ec533Spatrick namespace __dfsan {
476d89ec533Spatrick 
477d89ec533Spatrick bool dfsan_inited = false;
478d89ec533Spatrick bool dfsan_init_is_running = false;
479d89ec533Spatrick 
dfsan_copy_memory(void * dst,const void * src,uptr size)480d89ec533Spatrick void dfsan_copy_memory(void *dst, const void *src, uptr size) {
481d89ec533Spatrick   internal_memcpy(dst, src, size);
482*810390e3Srobert   dfsan_mem_shadow_transfer(dst, src, size);
483d89ec533Spatrick   if (dfsan_get_track_origins())
484d89ec533Spatrick     dfsan_mem_origin_transfer(dst, src, size);
485d89ec533Spatrick }
486d89ec533Spatrick 
487d89ec533Spatrick // Releases the pages within the origin address range.
ReleaseOrigins(void * addr,uptr size)488d89ec533Spatrick static void ReleaseOrigins(void *addr, uptr size) {
489d89ec533Spatrick   const uptr beg_origin_addr = (uptr)__dfsan::origin_for(addr);
490d89ec533Spatrick   const void *end_addr = (void *)((uptr)addr + size);
491d89ec533Spatrick   const uptr end_origin_addr = (uptr)__dfsan::origin_for(end_addr);
492d89ec533Spatrick 
493d89ec533Spatrick   if (end_origin_addr - beg_origin_addr <
494d89ec533Spatrick       common_flags()->clear_shadow_mmap_threshold)
495d89ec533Spatrick     return;
496d89ec533Spatrick 
497d89ec533Spatrick   const uptr page_size = GetPageSizeCached();
498d89ec533Spatrick   const uptr beg_aligned = RoundUpTo(beg_origin_addr, page_size);
499d89ec533Spatrick   const uptr end_aligned = RoundDownTo(end_origin_addr, page_size);
500d89ec533Spatrick 
501d89ec533Spatrick   if (!MmapFixedSuperNoReserve(beg_aligned, end_aligned - beg_aligned))
502d89ec533Spatrick     Die();
503d89ec533Spatrick }
504d89ec533Spatrick 
WriteZeroShadowInRange(uptr beg,uptr end)505*810390e3Srobert static void WriteZeroShadowInRange(uptr beg, uptr end) {
506*810390e3Srobert   // Don't write the label if it is already the value we need it to be.
507*810390e3Srobert   // In a program where most addresses are not labeled, it is common that
508*810390e3Srobert   // a page of shadow memory is entirely zeroed.  The Linux copy-on-write
509*810390e3Srobert   // implementation will share all of the zeroed pages, making a copy of a
510*810390e3Srobert   // page when any value is written.  The un-sharing will happen even if
511*810390e3Srobert   // the value written does not change the value in memory.  Avoiding the
512*810390e3Srobert   // write when both |label| and |*labelp| are zero dramatically reduces
513*810390e3Srobert   // the amount of real memory used by large programs.
514*810390e3Srobert   if (!mem_is_zero((const char *)beg, end - beg))
515*810390e3Srobert     internal_memset((void *)beg, 0, end - beg);
516*810390e3Srobert }
517*810390e3Srobert 
518d89ec533Spatrick // Releases the pages within the shadow address range, and sets
519d89ec533Spatrick // the shadow addresses not on the pages to be 0.
ReleaseOrClearShadows(void * addr,uptr size)520d89ec533Spatrick static void ReleaseOrClearShadows(void *addr, uptr size) {
521d89ec533Spatrick   const uptr beg_shadow_addr = (uptr)__dfsan::shadow_for(addr);
522d89ec533Spatrick   const void *end_addr = (void *)((uptr)addr + size);
523d89ec533Spatrick   const uptr end_shadow_addr = (uptr)__dfsan::shadow_for(end_addr);
524d89ec533Spatrick 
525d89ec533Spatrick   if (end_shadow_addr - beg_shadow_addr <
526*810390e3Srobert       common_flags()->clear_shadow_mmap_threshold) {
527*810390e3Srobert     WriteZeroShadowInRange(beg_shadow_addr, end_shadow_addr);
528*810390e3Srobert     return;
529*810390e3Srobert   }
530d89ec533Spatrick 
531d89ec533Spatrick   const uptr page_size = GetPageSizeCached();
532d89ec533Spatrick   const uptr beg_aligned = RoundUpTo(beg_shadow_addr, page_size);
533d89ec533Spatrick   const uptr end_aligned = RoundDownTo(end_shadow_addr, page_size);
534d89ec533Spatrick 
535d89ec533Spatrick   if (beg_aligned >= end_aligned) {
536*810390e3Srobert     WriteZeroShadowInRange(beg_shadow_addr, end_shadow_addr);
537d89ec533Spatrick   } else {
538d89ec533Spatrick     if (beg_aligned != beg_shadow_addr)
539*810390e3Srobert       WriteZeroShadowInRange(beg_shadow_addr, beg_aligned);
540d89ec533Spatrick     if (end_aligned != end_shadow_addr)
541*810390e3Srobert       WriteZeroShadowInRange(end_aligned, end_shadow_addr);
542d89ec533Spatrick     if (!MmapFixedSuperNoReserve(beg_aligned, end_aligned - beg_aligned))
543d89ec533Spatrick       Die();
544d89ec533Spatrick   }
545d89ec533Spatrick }
546d89ec533Spatrick 
SetShadow(dfsan_label label,void * addr,uptr size,dfsan_origin origin)547d89ec533Spatrick void SetShadow(dfsan_label label, void *addr, uptr size, dfsan_origin origin) {
548d89ec533Spatrick   if (0 != label) {
549d89ec533Spatrick     const uptr beg_shadow_addr = (uptr)__dfsan::shadow_for(addr);
550*810390e3Srobert     internal_memset((void *)beg_shadow_addr, label, size);
551d89ec533Spatrick     if (dfsan_get_track_origins())
552d89ec533Spatrick       SetOrigin(addr, size, origin);
553d89ec533Spatrick     return;
554d89ec533Spatrick   }
555d89ec533Spatrick 
556d89ec533Spatrick   if (dfsan_get_track_origins())
557d89ec533Spatrick     ReleaseOrigins(addr, size);
558d89ec533Spatrick 
559d89ec533Spatrick   ReleaseOrClearShadows(addr, size);
560d89ec533Spatrick }
561d89ec533Spatrick 
562*810390e3Srobert }  // namespace __dfsan
563*810390e3Srobert 
564*810390e3Srobert // If the label s is tainted, set the size bytes from the address p to be a new
565*810390e3Srobert // origin chain with the previous ID o and the current stack trace. This is
566*810390e3Srobert // used by instrumentation to reduce code size when too much code is inserted.
__dfsan_maybe_store_origin(dfsan_label s,void * p,uptr size,dfsan_origin o)567*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_maybe_store_origin(
568*810390e3Srobert     dfsan_label s, void *p, uptr size, dfsan_origin o) {
569*810390e3Srobert   if (UNLIKELY(s)) {
570*810390e3Srobert     GET_CALLER_PC_BP_SP;
571*810390e3Srobert     (void)sp;
572*810390e3Srobert     GET_STORE_STACK_TRACE_PC_BP(pc, bp);
573*810390e3Srobert     SetOrigin(p, size, ChainOrigin(o, &stack));
574*810390e3Srobert   }
575*810390e3Srobert }
576*810390e3Srobert 
__dfsan_set_label(dfsan_label label,dfsan_origin origin,void * addr,uptr size)577d89ec533Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_set_label(
578d89ec533Spatrick     dfsan_label label, dfsan_origin origin, void *addr, uptr size) {
579*810390e3Srobert   __dfsan::SetShadow(label, addr, size, origin);
580d89ec533Spatrick }
581d89ec533Spatrick 
5823cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
dfsan_set_label(dfsan_label label,void * addr,uptr size)5833cab2bb3Spatrick void dfsan_set_label(dfsan_label label, void *addr, uptr size) {
584d89ec533Spatrick   dfsan_origin init_origin = 0;
585d89ec533Spatrick   if (label && dfsan_get_track_origins()) {
586d89ec533Spatrick     GET_CALLER_PC_BP;
587d89ec533Spatrick     GET_STORE_STACK_TRACE_PC_BP(pc, bp);
588d89ec533Spatrick     init_origin = ChainOrigin(0, &stack, true);
589d89ec533Spatrick   }
590*810390e3Srobert   __dfsan::SetShadow(label, addr, size, init_origin);
5913cab2bb3Spatrick }
5923cab2bb3Spatrick 
5933cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
dfsan_add_label(dfsan_label label,void * addr,uptr size)5943cab2bb3Spatrick void dfsan_add_label(dfsan_label label, void *addr, uptr size) {
595d89ec533Spatrick   if (0 == label)
596d89ec533Spatrick     return;
597d89ec533Spatrick 
598d89ec533Spatrick   if (dfsan_get_track_origins()) {
599d89ec533Spatrick     GET_CALLER_PC_BP;
600d89ec533Spatrick     GET_STORE_STACK_TRACE_PC_BP(pc, bp);
601d89ec533Spatrick     dfsan_origin init_origin = ChainOrigin(0, &stack, true);
602d89ec533Spatrick     SetOrigin(addr, size, init_origin);
603d89ec533Spatrick   }
604d89ec533Spatrick 
6053cab2bb3Spatrick   for (dfsan_label *labelp = shadow_for(addr); size != 0; --size, ++labelp)
606d89ec533Spatrick     *labelp |= label;
6073cab2bb3Spatrick }
6083cab2bb3Spatrick 
6093cab2bb3Spatrick // Unlike the other dfsan interface functions the behavior of this function
6103cab2bb3Spatrick // depends on the label of one of its arguments.  Hence it is implemented as a
6113cab2bb3Spatrick // custom function.
6123cab2bb3Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
__dfsw_dfsan_get_label(long data,dfsan_label data_label,dfsan_label * ret_label)6133cab2bb3Spatrick __dfsw_dfsan_get_label(long data, dfsan_label data_label,
6143cab2bb3Spatrick                        dfsan_label *ret_label) {
6153cab2bb3Spatrick   *ret_label = 0;
6163cab2bb3Spatrick   return data_label;
6173cab2bb3Spatrick }
6183cab2bb3Spatrick 
__dfso_dfsan_get_label(long data,dfsan_label data_label,dfsan_label * ret_label,dfsan_origin data_origin,dfsan_origin * ret_origin)619d89ec533Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label __dfso_dfsan_get_label(
620d89ec533Spatrick     long data, dfsan_label data_label, dfsan_label *ret_label,
621d89ec533Spatrick     dfsan_origin data_origin, dfsan_origin *ret_origin) {
622d89ec533Spatrick   *ret_label = 0;
623d89ec533Spatrick   *ret_origin = 0;
624d89ec533Spatrick   return data_label;
625d89ec533Spatrick }
626d89ec533Spatrick 
627d89ec533Spatrick // This function is used if dfsan_get_origin is called when origin tracking is
628d89ec533Spatrick // off.
__dfsw_dfsan_get_origin(long data,dfsan_label data_label,dfsan_label * ret_label)629d89ec533Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin __dfsw_dfsan_get_origin(
630d89ec533Spatrick     long data, dfsan_label data_label, dfsan_label *ret_label) {
631d89ec533Spatrick   *ret_label = 0;
632d89ec533Spatrick   return 0;
633d89ec533Spatrick }
634d89ec533Spatrick 
__dfso_dfsan_get_origin(long data,dfsan_label data_label,dfsan_label * ret_label,dfsan_origin data_origin,dfsan_origin * ret_origin)635d89ec533Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin __dfso_dfsan_get_origin(
636d89ec533Spatrick     long data, dfsan_label data_label, dfsan_label *ret_label,
637d89ec533Spatrick     dfsan_origin data_origin, dfsan_origin *ret_origin) {
638d89ec533Spatrick   *ret_label = 0;
639d89ec533Spatrick   *ret_origin = 0;
640d89ec533Spatrick   return data_origin;
641d89ec533Spatrick }
642d89ec533Spatrick 
6433cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
dfsan_read_label(const void * addr,uptr size)6443cab2bb3Spatrick dfsan_read_label(const void *addr, uptr size) {
6453cab2bb3Spatrick   if (size == 0)
6463cab2bb3Spatrick     return 0;
6473cab2bb3Spatrick   return __dfsan_union_load(shadow_for(addr), size);
6483cab2bb3Spatrick }
6493cab2bb3Spatrick 
650d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
dfsan_read_origin_of_first_taint(const void * addr,uptr size)651d89ec533Spatrick dfsan_read_origin_of_first_taint(const void *addr, uptr size) {
652d89ec533Spatrick   return GetOriginIfTainted((uptr)addr, size);
653d89ec533Spatrick }
654d89ec533Spatrick 
dfsan_set_label_origin(dfsan_label label,dfsan_origin origin,void * addr,uptr size)655d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE void dfsan_set_label_origin(dfsan_label label,
656d89ec533Spatrick                                                           dfsan_origin origin,
657d89ec533Spatrick                                                           void *addr,
658d89ec533Spatrick                                                           uptr size) {
659d89ec533Spatrick   __dfsan_set_label(label, origin, addr, size);
6603cab2bb3Spatrick }
6613cab2bb3Spatrick 
6623cab2bb3Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE int
dfsan_has_label(dfsan_label label,dfsan_label elem)6633cab2bb3Spatrick dfsan_has_label(dfsan_label label, dfsan_label elem) {
664d89ec533Spatrick   return (label & elem) == elem;
6653cab2bb3Spatrick }
6663cab2bb3Spatrick 
667*810390e3Srobert namespace __dfsan {
668*810390e3Srobert 
669*810390e3Srobert typedef void (*dfsan_conditional_callback_t)(dfsan_label label,
670*810390e3Srobert                                              dfsan_origin origin);
671*810390e3Srobert static dfsan_conditional_callback_t conditional_callback = nullptr;
672*810390e3Srobert static dfsan_label labels_in_signal_conditional = 0;
673*810390e3Srobert 
ConditionalCallback(dfsan_label label,dfsan_origin origin)674*810390e3Srobert static void ConditionalCallback(dfsan_label label, dfsan_origin origin) {
675*810390e3Srobert   // Programs have many branches. For efficiency the conditional sink callback
676*810390e3Srobert   // handler needs to ignore as many as possible as early as possible.
677*810390e3Srobert   if (label == 0) {
678*810390e3Srobert     return;
679*810390e3Srobert   }
680*810390e3Srobert   if (conditional_callback == nullptr) {
681*810390e3Srobert     return;
682*810390e3Srobert   }
683*810390e3Srobert 
684*810390e3Srobert   // This initial ConditionalCallback handler needs to be in here in dfsan
685*810390e3Srobert   // runtime (rather than being an entirely user implemented hook) so that it
686*810390e3Srobert   // has access to dfsan thread information.
687*810390e3Srobert   DFsanThread *t = GetCurrentThread();
688*810390e3Srobert   // A callback operation which does useful work (like record the flow) will
689*810390e3Srobert   // likely be too long executed in a signal handler.
690*810390e3Srobert   if (t && t->InSignalHandler()) {
691*810390e3Srobert     // Record set of labels used in signal handler for completeness.
692*810390e3Srobert     labels_in_signal_conditional |= label;
693*810390e3Srobert     return;
694*810390e3Srobert   }
695*810390e3Srobert 
696*810390e3Srobert   conditional_callback(label, origin);
697*810390e3Srobert }
698*810390e3Srobert 
699*810390e3Srobert }  // namespace __dfsan
700*810390e3Srobert 
701*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__dfsan_conditional_callback_origin(dfsan_label label,dfsan_origin origin)702*810390e3Srobert __dfsan_conditional_callback_origin(dfsan_label label, dfsan_origin origin) {
703*810390e3Srobert   __dfsan::ConditionalCallback(label, origin);
704*810390e3Srobert }
705*810390e3Srobert 
__dfsan_conditional_callback(dfsan_label label)706*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_conditional_callback(
707*810390e3Srobert     dfsan_label label) {
708*810390e3Srobert   __dfsan::ConditionalCallback(label, 0);
709*810390e3Srobert }
710*810390e3Srobert 
dfsan_set_conditional_callback(__dfsan::dfsan_conditional_callback_t callback)711*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_set_conditional_callback(
712*810390e3Srobert     __dfsan::dfsan_conditional_callback_t callback) {
713*810390e3Srobert   __dfsan::conditional_callback = callback;
714*810390e3Srobert }
715*810390e3Srobert 
716*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
dfsan_get_labels_in_signal_conditional()717*810390e3Srobert dfsan_get_labels_in_signal_conditional() {
718*810390e3Srobert   return __dfsan::labels_in_signal_conditional;
719*810390e3Srobert }
720*810390e3Srobert 
721*810390e3Srobert namespace __dfsan {
722*810390e3Srobert 
723*810390e3Srobert typedef void (*dfsan_reaches_function_callback_t)(dfsan_label label,
724*810390e3Srobert                                                   dfsan_origin origin,
725*810390e3Srobert                                                   const char *file,
726*810390e3Srobert                                                   unsigned int line,
727*810390e3Srobert                                                   const char *function);
728*810390e3Srobert static dfsan_reaches_function_callback_t reaches_function_callback = nullptr;
729*810390e3Srobert static dfsan_label labels_in_signal_reaches_function = 0;
730*810390e3Srobert 
ReachesFunctionCallback(dfsan_label label,dfsan_origin origin,const char * file,unsigned int line,const char * function)731*810390e3Srobert static void ReachesFunctionCallback(dfsan_label label, dfsan_origin origin,
732*810390e3Srobert                                     const char *file, unsigned int line,
733*810390e3Srobert                                     const char *function) {
734*810390e3Srobert   if (label == 0) {
735*810390e3Srobert     return;
736*810390e3Srobert   }
737*810390e3Srobert   if (reaches_function_callback == nullptr) {
738*810390e3Srobert     return;
739*810390e3Srobert   }
740*810390e3Srobert 
741*810390e3Srobert   // This initial ReachesFunctionCallback handler needs to be in here in dfsan
742*810390e3Srobert   // runtime (rather than being an entirely user implemented hook) so that it
743*810390e3Srobert   // has access to dfsan thread information.
744*810390e3Srobert   DFsanThread *t = GetCurrentThread();
745*810390e3Srobert   // A callback operation which does useful work (like record the flow) will
746*810390e3Srobert   // likely be too long executed in a signal handler.
747*810390e3Srobert   if (t && t->InSignalHandler()) {
748*810390e3Srobert     // Record set of labels used in signal handler for completeness.
749*810390e3Srobert     labels_in_signal_reaches_function |= label;
750*810390e3Srobert     return;
751*810390e3Srobert   }
752*810390e3Srobert 
753*810390e3Srobert   reaches_function_callback(label, origin, file, line, function);
754*810390e3Srobert }
755*810390e3Srobert 
756*810390e3Srobert }  // namespace __dfsan
757*810390e3Srobert 
758*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__dfsan_reaches_function_callback_origin(dfsan_label label,dfsan_origin origin,const char * file,unsigned int line,const char * function)759*810390e3Srobert __dfsan_reaches_function_callback_origin(dfsan_label label, dfsan_origin origin,
760*810390e3Srobert                                          const char *file, unsigned int line,
761*810390e3Srobert                                          const char *function) {
762*810390e3Srobert   __dfsan::ReachesFunctionCallback(label, origin, file, line, function);
763*810390e3Srobert }
764*810390e3Srobert 
765*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__dfsan_reaches_function_callback(dfsan_label label,const char * file,unsigned int line,const char * function)766*810390e3Srobert __dfsan_reaches_function_callback(dfsan_label label, const char *file,
767*810390e3Srobert                                   unsigned int line, const char *function) {
768*810390e3Srobert   __dfsan::ReachesFunctionCallback(label, 0, file, line, function);
769*810390e3Srobert }
770*810390e3Srobert 
771*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
dfsan_set_reaches_function_callback(__dfsan::dfsan_reaches_function_callback_t callback)772*810390e3Srobert dfsan_set_reaches_function_callback(
773*810390e3Srobert     __dfsan::dfsan_reaches_function_callback_t callback) {
774*810390e3Srobert   __dfsan::reaches_function_callback = callback;
775*810390e3Srobert }
776*810390e3Srobert 
777*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
dfsan_get_labels_in_signal_reaches_function()778*810390e3Srobert dfsan_get_labels_in_signal_reaches_function() {
779*810390e3Srobert   return __dfsan::labels_in_signal_reaches_function;
780*810390e3Srobert }
781*810390e3Srobert 
782d89ec533Spatrick class Decorator : public __sanitizer::SanitizerCommonDecorator {
783d89ec533Spatrick  public:
Decorator()784d89ec533Spatrick   Decorator() : SanitizerCommonDecorator() {}
Origin() const785d89ec533Spatrick   const char *Origin() const { return Magenta(); }
786d89ec533Spatrick };
787d89ec533Spatrick 
788d89ec533Spatrick namespace {
789d89ec533Spatrick 
PrintNoOriginTrackingWarning()790d89ec533Spatrick void PrintNoOriginTrackingWarning() {
791d89ec533Spatrick   Decorator d;
792d89ec533Spatrick   Printf(
793d89ec533Spatrick       "  %sDFSan: origin tracking is not enabled. Did you specify the "
794d89ec533Spatrick       "-dfsan-track-origins=1 option?%s\n",
795d89ec533Spatrick       d.Warning(), d.Default());
7963cab2bb3Spatrick }
7973cab2bb3Spatrick 
PrintNoTaintWarning(const void * address)798d89ec533Spatrick void PrintNoTaintWarning(const void *address) {
799d89ec533Spatrick   Decorator d;
800d89ec533Spatrick   Printf("  %sDFSan: no tainted value at %x%s\n", d.Warning(), address,
801d89ec533Spatrick          d.Default());
8023cab2bb3Spatrick }
8033cab2bb3Spatrick 
PrintInvalidOriginWarning(dfsan_label label,const void * address)804d89ec533Spatrick void PrintInvalidOriginWarning(dfsan_label label, const void *address) {
805d89ec533Spatrick   Decorator d;
806d89ec533Spatrick   Printf(
807d89ec533Spatrick       "  %sTaint value 0x%x (at %p) has invalid origin tracking. This can "
808d89ec533Spatrick       "be a DFSan bug.%s\n",
809d89ec533Spatrick       d.Warning(), label, address, d.Default());
810d89ec533Spatrick }
8113cab2bb3Spatrick 
PrintInvalidOriginIdWarning(dfsan_origin origin)812*810390e3Srobert void PrintInvalidOriginIdWarning(dfsan_origin origin) {
813d89ec533Spatrick   Decorator d;
814*810390e3Srobert   Printf(
815*810390e3Srobert       "  %sOrigin Id %d has invalid origin tracking. This can "
816*810390e3Srobert       "be a DFSan bug.%s\n",
817*810390e3Srobert       d.Warning(), origin, d.Default());
818*810390e3Srobert }
819d89ec533Spatrick 
PrintOriginTraceFramesToStr(Origin o,InternalScopedString * out)820*810390e3Srobert bool PrintOriginTraceFramesToStr(Origin o, InternalScopedString *out) {
821*810390e3Srobert   Decorator d;
822d89ec533Spatrick   bool found = false;
823d89ec533Spatrick 
824d89ec533Spatrick   while (o.isChainedOrigin()) {
825d89ec533Spatrick     StackTrace stack;
826d89ec533Spatrick     dfsan_origin origin_id = o.raw_id();
827d89ec533Spatrick     o = o.getNextChainedOrigin(&stack);
828d89ec533Spatrick     if (o.isChainedOrigin())
829d89ec533Spatrick       out->append(
830d89ec533Spatrick           "  %sOrigin value: 0x%x, Taint value was stored to memory at%s\n",
831d89ec533Spatrick           d.Origin(), origin_id, d.Default());
832d89ec533Spatrick     else
833d89ec533Spatrick       out->append("  %sOrigin value: 0x%x, Taint value was created at%s\n",
834d89ec533Spatrick                   d.Origin(), origin_id, d.Default());
835d89ec533Spatrick 
836d89ec533Spatrick     // Includes a trailing newline, so no need to add it again.
837d89ec533Spatrick     stack.PrintTo(out);
838d89ec533Spatrick     found = true;
8393cab2bb3Spatrick   }
840d89ec533Spatrick 
841d89ec533Spatrick   return found;
8423cab2bb3Spatrick }
843d89ec533Spatrick 
PrintOriginTraceToStr(const void * addr,const char * description,InternalScopedString * out)844*810390e3Srobert bool PrintOriginTraceToStr(const void *addr, const char *description,
845*810390e3Srobert                            InternalScopedString *out) {
846*810390e3Srobert   CHECK(out);
847*810390e3Srobert   CHECK(dfsan_get_track_origins());
848*810390e3Srobert   Decorator d;
849*810390e3Srobert 
850*810390e3Srobert   const dfsan_label label = *__dfsan::shadow_for(addr);
851*810390e3Srobert   CHECK(label);
852*810390e3Srobert 
853*810390e3Srobert   const dfsan_origin origin = *__dfsan::origin_for(addr);
854*810390e3Srobert 
855*810390e3Srobert   out->append("  %sTaint value 0x%x (at %p) origin tracking (%s)%s\n",
856*810390e3Srobert               d.Origin(), label, addr, description ? description : "",
857*810390e3Srobert               d.Default());
858*810390e3Srobert 
859*810390e3Srobert   Origin o = Origin::FromRawId(origin);
860*810390e3Srobert   return PrintOriginTraceFramesToStr(o, out);
861*810390e3Srobert }
862*810390e3Srobert 
863d89ec533Spatrick }  // namespace
864d89ec533Spatrick 
dfsan_print_origin_trace(const void * addr,const char * description)865d89ec533Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_trace(
866d89ec533Spatrick     const void *addr, const char *description) {
867d89ec533Spatrick   if (!dfsan_get_track_origins()) {
868d89ec533Spatrick     PrintNoOriginTrackingWarning();
869d89ec533Spatrick     return;
870d89ec533Spatrick   }
871d89ec533Spatrick 
872d89ec533Spatrick   const dfsan_label label = *__dfsan::shadow_for(addr);
873d89ec533Spatrick   if (!label) {
874d89ec533Spatrick     PrintNoTaintWarning(addr);
875d89ec533Spatrick     return;
876d89ec533Spatrick   }
877d89ec533Spatrick 
878d89ec533Spatrick   InternalScopedString trace;
879d89ec533Spatrick   bool success = PrintOriginTraceToStr(addr, description, &trace);
880d89ec533Spatrick 
881d89ec533Spatrick   if (trace.length())
882d89ec533Spatrick     Printf("%s", trace.data());
883d89ec533Spatrick 
884d89ec533Spatrick   if (!success)
885d89ec533Spatrick     PrintInvalidOriginWarning(label, addr);
886d89ec533Spatrick }
887d89ec533Spatrick 
888*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr
dfsan_sprint_origin_trace(const void * addr,const char * description,char * out_buf,uptr out_buf_size)889d89ec533Spatrick dfsan_sprint_origin_trace(const void *addr, const char *description,
890*810390e3Srobert                           char *out_buf, uptr out_buf_size) {
891d89ec533Spatrick   CHECK(out_buf);
892d89ec533Spatrick 
893d89ec533Spatrick   if (!dfsan_get_track_origins()) {
894d89ec533Spatrick     PrintNoOriginTrackingWarning();
895d89ec533Spatrick     return 0;
896d89ec533Spatrick   }
897d89ec533Spatrick 
898d89ec533Spatrick   const dfsan_label label = *__dfsan::shadow_for(addr);
899d89ec533Spatrick   if (!label) {
900d89ec533Spatrick     PrintNoTaintWarning(addr);
901d89ec533Spatrick     return 0;
902d89ec533Spatrick   }
903d89ec533Spatrick 
904d89ec533Spatrick   InternalScopedString trace;
905d89ec533Spatrick   bool success = PrintOriginTraceToStr(addr, description, &trace);
906d89ec533Spatrick 
907d89ec533Spatrick   if (!success) {
908d89ec533Spatrick     PrintInvalidOriginWarning(label, addr);
909d89ec533Spatrick     return 0;
910d89ec533Spatrick   }
911d89ec533Spatrick 
912d89ec533Spatrick   if (out_buf_size) {
913d89ec533Spatrick     internal_strncpy(out_buf, trace.data(), out_buf_size - 1);
914d89ec533Spatrick     out_buf[out_buf_size - 1] = '\0';
915d89ec533Spatrick   }
916d89ec533Spatrick 
917d89ec533Spatrick   return trace.length();
918d89ec533Spatrick }
919d89ec533Spatrick 
dfsan_print_origin_id_trace(dfsan_origin origin)920*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE void dfsan_print_origin_id_trace(
921*810390e3Srobert     dfsan_origin origin) {
922*810390e3Srobert   if (!dfsan_get_track_origins()) {
923*810390e3Srobert     PrintNoOriginTrackingWarning();
924*810390e3Srobert     return;
925*810390e3Srobert   }
926*810390e3Srobert   Origin o = Origin::FromRawId(origin);
927*810390e3Srobert 
928*810390e3Srobert   InternalScopedString trace;
929*810390e3Srobert   bool success = PrintOriginTraceFramesToStr(o, &trace);
930*810390e3Srobert 
931*810390e3Srobert   if (trace.length())
932*810390e3Srobert     Printf("%s", trace.data());
933*810390e3Srobert 
934*810390e3Srobert   if (!success)
935*810390e3Srobert     PrintInvalidOriginIdWarning(origin);
936*810390e3Srobert }
937*810390e3Srobert 
dfsan_sprint_origin_id_trace(dfsan_origin origin,char * out_buf,uptr out_buf_size)938*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr dfsan_sprint_origin_id_trace(
939*810390e3Srobert     dfsan_origin origin, char *out_buf, uptr out_buf_size) {
940*810390e3Srobert   CHECK(out_buf);
941*810390e3Srobert 
942*810390e3Srobert   if (!dfsan_get_track_origins()) {
943*810390e3Srobert     PrintNoOriginTrackingWarning();
944*810390e3Srobert     return 0;
945*810390e3Srobert   }
946*810390e3Srobert   Origin o = Origin::FromRawId(origin);
947*810390e3Srobert 
948*810390e3Srobert   InternalScopedString trace;
949*810390e3Srobert   bool success = PrintOriginTraceFramesToStr(o, &trace);
950*810390e3Srobert 
951*810390e3Srobert   if (!success) {
952*810390e3Srobert     PrintInvalidOriginIdWarning(origin);
953*810390e3Srobert     return 0;
954*810390e3Srobert   }
955*810390e3Srobert 
956*810390e3Srobert   if (out_buf_size) {
957*810390e3Srobert     internal_strncpy(out_buf, trace.data(), out_buf_size - 1);
958*810390e3Srobert     out_buf[out_buf_size - 1] = '\0';
959*810390e3Srobert   }
960*810390e3Srobert 
961*810390e3Srobert   return trace.length();
962*810390e3Srobert }
963*810390e3Srobert 
964d89ec533Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
dfsan_get_init_origin(const void * addr)965d89ec533Spatrick dfsan_get_init_origin(const void *addr) {
966d89ec533Spatrick   if (!dfsan_get_track_origins())
967d89ec533Spatrick     return 0;
968d89ec533Spatrick 
969d89ec533Spatrick   const dfsan_label label = *__dfsan::shadow_for(addr);
970d89ec533Spatrick   if (!label)
971d89ec533Spatrick     return 0;
972d89ec533Spatrick 
973d89ec533Spatrick   const dfsan_origin origin = *__dfsan::origin_for(addr);
974d89ec533Spatrick 
975d89ec533Spatrick   Origin o = Origin::FromRawId(origin);
976d89ec533Spatrick   dfsan_origin origin_id = o.raw_id();
977d89ec533Spatrick   while (o.isChainedOrigin()) {
978d89ec533Spatrick     StackTrace stack;
979d89ec533Spatrick     origin_id = o.raw_id();
980d89ec533Spatrick     o = o.getNextChainedOrigin(&stack);
981d89ec533Spatrick   }
982d89ec533Spatrick   return origin_id;
983d89ec533Spatrick }
984d89ec533Spatrick 
UnwindImpl(uptr pc,uptr bp,void * context,bool request_fast,u32 max_depth)985d89ec533Spatrick void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp,
986d89ec533Spatrick                                                  void *context,
987d89ec533Spatrick                                                  bool request_fast,
988d89ec533Spatrick                                                  u32 max_depth) {
989d89ec533Spatrick   using namespace __dfsan;
990d89ec533Spatrick   DFsanThread *t = GetCurrentThread();
991d89ec533Spatrick   if (!t || !StackTrace::WillUseFastUnwind(request_fast)) {
992d89ec533Spatrick     return Unwind(max_depth, pc, bp, context, 0, 0, false);
993d89ec533Spatrick   }
994d89ec533Spatrick   Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), true);
995d89ec533Spatrick }
996d89ec533Spatrick 
__sanitizer_print_stack_trace()997d89ec533Spatrick extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_print_stack_trace() {
998d89ec533Spatrick   GET_CALLER_PC_BP;
999d89ec533Spatrick   GET_STORE_STACK_TRACE_PC_BP(pc, bp);
1000d89ec533Spatrick   stack.Print();
1001d89ec533Spatrick }
1002d89ec533Spatrick 
1003*810390e3Srobert extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr
dfsan_sprint_stack_trace(char * out_buf,uptr out_buf_size)1004*810390e3Srobert dfsan_sprint_stack_trace(char *out_buf, uptr out_buf_size) {
1005d89ec533Spatrick   CHECK(out_buf);
1006d89ec533Spatrick   GET_CALLER_PC_BP;
1007d89ec533Spatrick   GET_STORE_STACK_TRACE_PC_BP(pc, bp);
1008d89ec533Spatrick   return stack.PrintTo(out_buf, out_buf_size);
10093cab2bb3Spatrick }
10103cab2bb3Spatrick 
SetDefaults()10113cab2bb3Spatrick void Flags::SetDefaults() {
10123cab2bb3Spatrick #define DFSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
10133cab2bb3Spatrick #include "dfsan_flags.inc"
10143cab2bb3Spatrick #undef DFSAN_FLAG
10153cab2bb3Spatrick }
10163cab2bb3Spatrick 
RegisterDfsanFlags(FlagParser * parser,Flags * f)10173cab2bb3Spatrick static void RegisterDfsanFlags(FlagParser *parser, Flags *f) {
10183cab2bb3Spatrick #define DFSAN_FLAG(Type, Name, DefaultValue, Description) \
10193cab2bb3Spatrick   RegisterFlag(parser, #Name, Description, &f->Name);
10203cab2bb3Spatrick #include "dfsan_flags.inc"
10213cab2bb3Spatrick #undef DFSAN_FLAG
10223cab2bb3Spatrick }
10233cab2bb3Spatrick 
InitializeFlags()10243cab2bb3Spatrick static void InitializeFlags() {
10253cab2bb3Spatrick   SetCommonFlagsDefaults();
1026d89ec533Spatrick   {
1027d89ec533Spatrick     CommonFlags cf;
1028d89ec533Spatrick     cf.CopyFrom(*common_flags());
1029d89ec533Spatrick     cf.intercept_tls_get_addr = true;
1030d89ec533Spatrick     OverrideCommonFlags(cf);
1031d89ec533Spatrick   }
10323cab2bb3Spatrick   flags().SetDefaults();
10333cab2bb3Spatrick 
10343cab2bb3Spatrick   FlagParser parser;
10353cab2bb3Spatrick   RegisterCommonFlags(&parser);
10363cab2bb3Spatrick   RegisterDfsanFlags(&parser, &flags());
10373cab2bb3Spatrick   parser.ParseStringFromEnv("DFSAN_OPTIONS");
10383cab2bb3Spatrick   InitializeCommonFlags();
10393cab2bb3Spatrick   if (Verbosity()) ReportUnrecognizedFlags();
10403cab2bb3Spatrick   if (common_flags()->help) parser.PrintFlagDescriptions();
10413cab2bb3Spatrick }
10423cab2bb3Spatrick 
1043d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
dfsan_clear_arg_tls(uptr offset,uptr size)1044d89ec533Spatrick void dfsan_clear_arg_tls(uptr offset, uptr size) {
1045d89ec533Spatrick   internal_memset((void *)((uptr)__dfsan_arg_tls + offset), 0, size);
10463cab2bb3Spatrick }
10473cab2bb3Spatrick 
1048d89ec533Spatrick SANITIZER_INTERFACE_ATTRIBUTE
dfsan_clear_thread_local_state()1049d89ec533Spatrick void dfsan_clear_thread_local_state() {
1050d89ec533Spatrick   internal_memset(__dfsan_arg_tls, 0, sizeof(__dfsan_arg_tls));
1051d89ec533Spatrick   internal_memset(__dfsan_retval_tls, 0, sizeof(__dfsan_retval_tls));
10523cab2bb3Spatrick 
1053d89ec533Spatrick   if (dfsan_get_track_origins()) {
1054d89ec533Spatrick     internal_memset(__dfsan_arg_origin_tls, 0, sizeof(__dfsan_arg_origin_tls));
1055d89ec533Spatrick     internal_memset(&__dfsan_retval_origin_tls, 0,
1056d89ec533Spatrick                     sizeof(__dfsan_retval_origin_tls));
10573cab2bb3Spatrick   }
10583cab2bb3Spatrick }
10593cab2bb3Spatrick 
1060*810390e3Srobert SANITIZER_INTERFACE_ATTRIBUTE
dfsan_set_arg_tls(uptr offset,dfsan_label label)1061*810390e3Srobert void dfsan_set_arg_tls(uptr offset, dfsan_label label) {
1062*810390e3Srobert   // 2x to match ShadowTLSAlignment.
1063*810390e3Srobert   // ShadowTLSAlignment should probably be changed.
1064*810390e3Srobert   // TODO: Consider reducing ShadowTLSAlignment to 1.
1065*810390e3Srobert   // Aligning to 2 bytes is probably a remnant of fast16 mode.
1066*810390e3Srobert   ((dfsan_label *)__dfsan_arg_tls)[offset * 2] = label;
1067*810390e3Srobert }
1068*810390e3Srobert 
1069*810390e3Srobert SANITIZER_INTERFACE_ATTRIBUTE
dfsan_set_arg_origin_tls(uptr offset,dfsan_origin o)1070*810390e3Srobert void dfsan_set_arg_origin_tls(uptr offset, dfsan_origin o) {
1071*810390e3Srobert   __dfsan_arg_origin_tls[offset] = o;
1072*810390e3Srobert }
1073*810390e3Srobert 
dfsan_flush()10743cab2bb3Spatrick extern "C" void dfsan_flush() {
1075d89ec533Spatrick   const uptr maxVirtualAddress = GetMaxUserVirtualAddress();
1076d89ec533Spatrick   for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
1077d89ec533Spatrick     uptr start = kMemoryLayout[i].start;
1078d89ec533Spatrick     uptr end = kMemoryLayout[i].end;
1079d89ec533Spatrick     uptr size = end - start;
1080d89ec533Spatrick     MappingDesc::Type type = kMemoryLayout[i].type;
1081d89ec533Spatrick 
1082d89ec533Spatrick     if (type != MappingDesc::SHADOW && type != MappingDesc::ORIGIN)
1083d89ec533Spatrick       continue;
1084d89ec533Spatrick 
1085d89ec533Spatrick     // Check if the segment should be mapped based on platform constraints.
1086d89ec533Spatrick     if (start >= maxVirtualAddress)
1087d89ec533Spatrick       continue;
1088d89ec533Spatrick 
1089d89ec533Spatrick     if (!MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name)) {
1090d89ec533Spatrick       Printf("FATAL: DataFlowSanitizer: failed to clear memory region\n");
10913cab2bb3Spatrick       Die();
10923cab2bb3Spatrick     }
1093d89ec533Spatrick   }
1094*810390e3Srobert   __dfsan::labels_in_signal_conditional = 0;
1095*810390e3Srobert   __dfsan::labels_in_signal_reaches_function = 0;
1096d89ec533Spatrick }
10973cab2bb3Spatrick 
1098d89ec533Spatrick // TODO: CheckMemoryLayoutSanity is based on msan.
1099d89ec533Spatrick // Consider refactoring these into a shared implementation.
CheckMemoryLayoutSanity()1100d89ec533Spatrick static void CheckMemoryLayoutSanity() {
1101d89ec533Spatrick   uptr prev_end = 0;
1102d89ec533Spatrick   for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
1103d89ec533Spatrick     uptr start = kMemoryLayout[i].start;
1104d89ec533Spatrick     uptr end = kMemoryLayout[i].end;
1105d89ec533Spatrick     MappingDesc::Type type = kMemoryLayout[i].type;
1106d89ec533Spatrick     CHECK_LT(start, end);
1107d89ec533Spatrick     CHECK_EQ(prev_end, start);
1108d89ec533Spatrick     CHECK(addr_is_type(start, type));
1109d89ec533Spatrick     CHECK(addr_is_type((start + end) / 2, type));
1110d89ec533Spatrick     CHECK(addr_is_type(end - 1, type));
1111d89ec533Spatrick     if (type == MappingDesc::APP) {
1112d89ec533Spatrick       uptr addr = start;
1113d89ec533Spatrick       CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
1114d89ec533Spatrick       CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
1115d89ec533Spatrick       CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
1116d89ec533Spatrick 
1117d89ec533Spatrick       addr = (start + end) / 2;
1118d89ec533Spatrick       CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
1119d89ec533Spatrick       CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
1120d89ec533Spatrick       CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
1121d89ec533Spatrick 
1122d89ec533Spatrick       addr = end - 1;
1123d89ec533Spatrick       CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
1124d89ec533Spatrick       CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
1125d89ec533Spatrick       CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
1126d89ec533Spatrick     }
1127d89ec533Spatrick     prev_end = end;
1128d89ec533Spatrick   }
1129d89ec533Spatrick }
1130d89ec533Spatrick 
1131d89ec533Spatrick // TODO: CheckMemoryRangeAvailability is based on msan.
1132d89ec533Spatrick // Consider refactoring these into a shared implementation.
CheckMemoryRangeAvailability(uptr beg,uptr size)1133d89ec533Spatrick static bool CheckMemoryRangeAvailability(uptr beg, uptr size) {
1134d89ec533Spatrick   if (size > 0) {
1135d89ec533Spatrick     uptr end = beg + size - 1;
1136d89ec533Spatrick     if (!MemoryRangeIsAvailable(beg, end)) {
1137d89ec533Spatrick       Printf("FATAL: Memory range %p - %p is not available.\n", beg, end);
1138d89ec533Spatrick       return false;
1139d89ec533Spatrick     }
1140d89ec533Spatrick   }
1141d89ec533Spatrick   return true;
1142d89ec533Spatrick }
1143d89ec533Spatrick 
1144d89ec533Spatrick // TODO: ProtectMemoryRange is based on msan.
1145d89ec533Spatrick // Consider refactoring these into a shared implementation.
ProtectMemoryRange(uptr beg,uptr size,const char * name)1146d89ec533Spatrick static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) {
1147d89ec533Spatrick   if (size > 0) {
1148d89ec533Spatrick     void *addr = MmapFixedNoAccess(beg, size, name);
1149d89ec533Spatrick     if (beg == 0 && addr) {
1150d89ec533Spatrick       // Depending on the kernel configuration, we may not be able to protect
1151d89ec533Spatrick       // the page at address zero.
1152d89ec533Spatrick       uptr gap = 16 * GetPageSizeCached();
1153d89ec533Spatrick       beg += gap;
1154d89ec533Spatrick       size -= gap;
1155d89ec533Spatrick       addr = MmapFixedNoAccess(beg, size, name);
1156d89ec533Spatrick     }
1157d89ec533Spatrick     if ((uptr)addr != beg) {
1158d89ec533Spatrick       uptr end = beg + size - 1;
1159d89ec533Spatrick       Printf("FATAL: Cannot protect memory range %p - %p (%s).\n", beg, end,
1160d89ec533Spatrick              name);
1161d89ec533Spatrick       return false;
1162d89ec533Spatrick     }
1163d89ec533Spatrick   }
1164d89ec533Spatrick   return true;
1165d89ec533Spatrick }
1166d89ec533Spatrick 
1167d89ec533Spatrick // TODO: InitShadow is based on msan.
1168d89ec533Spatrick // Consider refactoring these into a shared implementation.
InitShadow(bool init_origins)1169d89ec533Spatrick bool InitShadow(bool init_origins) {
1170d89ec533Spatrick   // Let user know mapping parameters first.
1171*810390e3Srobert   VPrintf(1, "dfsan_init %p\n", (void *)&__dfsan::dfsan_init);
1172d89ec533Spatrick   for (unsigned i = 0; i < kMemoryLayoutSize; ++i)
1173d89ec533Spatrick     VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start,
1174d89ec533Spatrick             kMemoryLayout[i].end - 1);
1175d89ec533Spatrick 
1176d89ec533Spatrick   CheckMemoryLayoutSanity();
1177d89ec533Spatrick 
1178d89ec533Spatrick   if (!MEM_IS_APP(&__dfsan::dfsan_init)) {
1179d89ec533Spatrick     Printf("FATAL: Code %p is out of application range. Non-PIE build?\n",
1180d89ec533Spatrick            (uptr)&__dfsan::dfsan_init);
1181d89ec533Spatrick     return false;
1182d89ec533Spatrick   }
1183d89ec533Spatrick 
1184d89ec533Spatrick   const uptr maxVirtualAddress = GetMaxUserVirtualAddress();
1185d89ec533Spatrick 
1186d89ec533Spatrick   for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
1187d89ec533Spatrick     uptr start = kMemoryLayout[i].start;
1188d89ec533Spatrick     uptr end = kMemoryLayout[i].end;
1189d89ec533Spatrick     uptr size = end - start;
1190d89ec533Spatrick     MappingDesc::Type type = kMemoryLayout[i].type;
1191d89ec533Spatrick 
1192d89ec533Spatrick     // Check if the segment should be mapped based on platform constraints.
1193d89ec533Spatrick     if (start >= maxVirtualAddress)
1194d89ec533Spatrick       continue;
1195d89ec533Spatrick 
1196d89ec533Spatrick     bool map = type == MappingDesc::SHADOW ||
1197d89ec533Spatrick                (init_origins && type == MappingDesc::ORIGIN);
1198d89ec533Spatrick     bool protect = type == MappingDesc::INVALID ||
1199d89ec533Spatrick                    (!init_origins && type == MappingDesc::ORIGIN);
1200d89ec533Spatrick     CHECK(!(map && protect));
1201d89ec533Spatrick     if (!map && !protect)
1202d89ec533Spatrick       CHECK(type == MappingDesc::APP);
1203d89ec533Spatrick     if (map) {
1204d89ec533Spatrick       if (!CheckMemoryRangeAvailability(start, size))
1205d89ec533Spatrick         return false;
1206d89ec533Spatrick       if (!MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name))
1207d89ec533Spatrick         return false;
1208d89ec533Spatrick       if (common_flags()->use_madv_dontdump)
1209d89ec533Spatrick         DontDumpShadowMemory(start, size);
1210d89ec533Spatrick     }
1211d89ec533Spatrick     if (protect) {
1212d89ec533Spatrick       if (!CheckMemoryRangeAvailability(start, size))
1213d89ec533Spatrick         return false;
1214d89ec533Spatrick       if (!ProtectMemoryRange(start, size, kMemoryLayout[i].name))
1215d89ec533Spatrick         return false;
1216d89ec533Spatrick     }
1217d89ec533Spatrick   }
1218d89ec533Spatrick 
1219d89ec533Spatrick   return true;
1220d89ec533Spatrick }
1221d89ec533Spatrick 
DFsanInit(int argc,char ** argv,char ** envp)1222d89ec533Spatrick static void DFsanInit(int argc, char **argv, char **envp) {
1223d89ec533Spatrick   CHECK(!dfsan_init_is_running);
1224d89ec533Spatrick   if (dfsan_inited)
1225d89ec533Spatrick     return;
1226d89ec533Spatrick   dfsan_init_is_running = true;
1227d89ec533Spatrick   SanitizerToolName = "DataflowSanitizer";
1228d89ec533Spatrick 
1229d89ec533Spatrick   AvoidCVE_2016_2143();
1230d89ec533Spatrick 
12313cab2bb3Spatrick   InitializeFlags();
12323cab2bb3Spatrick 
1233d89ec533Spatrick   CheckASLR();
12343cab2bb3Spatrick 
1235d89ec533Spatrick   InitShadow(dfsan_get_track_origins());
12363cab2bb3Spatrick 
1237d89ec533Spatrick   initialize_interceptors();
12383cab2bb3Spatrick 
1239d89ec533Spatrick   // Set up threads
1240d89ec533Spatrick   DFsanTSDInit(DFsanTSDDtor);
12413cab2bb3Spatrick 
1242d89ec533Spatrick   dfsan_allocator_init();
12433cab2bb3Spatrick 
1244*810390e3Srobert   DFsanThread *main_thread = DFsanThread::Create(nullptr, nullptr);
1245d89ec533Spatrick   SetCurrentThread(main_thread);
1246*810390e3Srobert   main_thread->Init();
1247d89ec533Spatrick 
1248d89ec533Spatrick   dfsan_init_is_running = false;
1249d89ec533Spatrick   dfsan_inited = true;
12503cab2bb3Spatrick }
12513cab2bb3Spatrick 
1252d89ec533Spatrick namespace __dfsan {
1253d89ec533Spatrick 
dfsan_init()1254d89ec533Spatrick void dfsan_init() { DFsanInit(0, nullptr, nullptr); }
1255d89ec533Spatrick 
1256d89ec533Spatrick }  // namespace __dfsan
1257d89ec533Spatrick 
12583cab2bb3Spatrick #if SANITIZER_CAN_USE_PREINIT_ARRAY
1259d89ec533Spatrick __attribute__((section(".preinit_array"),
1260d89ec533Spatrick                used)) static void (*dfsan_init_ptr)(int, char **,
1261d89ec533Spatrick                                                     char **) = DFsanInit;
12623cab2bb3Spatrick #endif
1263