1 //===-- dfsan.cpp ---------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of DataFlowSanitizer.
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).
16 // The public interface is defined in include/sanitizer/dfsan_interface.h whose
17 // functions are prefixed dfsan_ while the compiler interface functions are
19 //===----------------------------------------------------------------------===//
21 #include "dfsan/dfsan.h"
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"
37 using namespace __dfsan
;
39 Flags
__dfsan::flags_data
;
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;
47 SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u64
48 __dfsan_retval_tls
[kDFsanRetvalTlsSize
/ sizeof(u64
)];
49 SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u32 __dfsan_retval_origin_tls
;
50 SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u64
51 __dfsan_arg_tls
[kDFsanArgTlsSize
/ sizeof(u64
)];
52 SANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL u32
53 __dfsan_arg_origin_tls
[kDFsanArgOriginTlsSize
/ sizeof(u32
)];
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
const int __dfsan_track_origins
;
62 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
int dfsan_get_track_origins() {
63 return &__dfsan_track_origins
? __dfsan_track_origins
: 0;
66 // On Linux/x86_64, memory is laid out as follows:
68 // +--------------------+ 0x800000000000 (top of memory)
70 // +--------------------+ 0x700000000000
72 // +--------------------+ 0x610000000000
74 // +--------------------+ 0x600000000000
76 // +--------------------+ 0x510000000000
78 // +--------------------+ 0x500000000000
80 // +--------------------+ 0x400000000000
82 // +--------------------+ 0x300000000000
84 // +--------------------+ 0x200000000000
86 // +--------------------+ 0x110000000000
88 // +--------------------+ 0x100000000000
90 // +--------------------+ 0x010000000000
92 // +--------------------+ 0x000000000000
94 // MEM_TO_SHADOW(mem) = mem ^ 0x500000000000
95 // SHADOW_TO_ORIGIN(shadow) = shadow + 0x100000000000
97 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
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
)
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 u64
108 __dfsan_load_label_and_origin(const void *addr
, uptr n
) {
109 dfsan_label label
= 0;
112 dfsan_label
*s
= shadow_for((void *)p
);
113 for (uptr i
= 0; i
< n
; ++i
) {
114 dfsan_label l
= s
[i
];
119 ret
= *(dfsan_origin
*)origin_for((void *)(p
+ i
));
121 return ret
| (u64
)label
<< 32;
124 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
125 void __dfsan_unimplemented(char *fname
) {
126 if (flags().warn_unimplemented
)
127 Report("WARNING: DataFlowSanitizer: call to uninstrumented function %s\n",
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
void __dfsan_nonzero_label() {
135 if (flags().warn_nonzero_labels
)
136 Report("WARNING: DataFlowSanitizer: saw nonzero label\n");
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
void
142 __dfsan_vararg_wrapper(const char *fname
) {
143 Report("FATAL: DataFlowSanitizer: unsupported indirect call to vararg "
144 "function %s\n", fname
);
148 // Resolves the union of two labels.
149 SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
150 dfsan_union(dfsan_label l1
, dfsan_label l2
) {
154 static const uptr kOriginAlign
= sizeof(dfsan_origin
);
155 static const uptr kOriginAlignMask
= ~(kOriginAlign
- 1UL);
157 static uptr
OriginAlignUp(uptr u
) {
158 return (u
+ kOriginAlign
- 1) & kOriginAlignMask
;
161 static uptr
OriginAlignDown(uptr u
) { return u
& kOriginAlignMask
; }
163 // Return the origin of the first taint byte in the size bytes from the address
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
);
170 // Validate address region.
171 CHECK(MEM_IS_SHADOW(s
));
172 return *(dfsan_origin
*)origin_for((void *)addr
);
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) \
184 BufferedStackTrace stack; \
185 stack.Unwind(pc, bp, nullptr, true, flags().store_context_size);
187 #define PRINT_CALLER_STACK_TRACE \
189 GET_CALLER_PC_BP_SP; \
191 GET_STORE_STACK_TRACE_PC_BP(pc, bp) \
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
200 DFsanThread
*t
= GetCurrentThread();
201 if (t
&& t
->InSignalHandler())
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
&& id
== 0 && flags().check_origin_invariant
) {
210 Printf(" DFSan found invalid origin invariant\n");
211 PRINT_CALLER_STACK_TRACE
214 Origin o
= Origin::FromRawId(id
);
215 stack
->tag
= StackTrace::TAG_UNKNOWN
;
216 Origin chained
= Origin::CreateChainedOrigin(o
, stack
);
217 return chained
.raw_id();
220 static void ChainAndWriteOriginIfTainted(uptr src
, uptr size
, uptr dst
,
222 dfsan_origin o
= GetOriginIfTainted(src
, size
);
224 o
= ChainOrigin(o
, stack
);
225 *(dfsan_origin
*)origin_for((void *)dst
) = o
;
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
,
237 uptr beg
= OriginAlignDown(d
);
238 // Copy left unaligned origin if that memory is tainted.
240 ChainAndWriteOriginIfTainted((uptr
)src
, beg
+ kOriginAlign
- d
, beg
, stack
);
244 uptr end
= OriginAlignDown(d
+ size
);
245 // If both ends fall into the same 4-byte slot, we are done.
249 // Copy right unaligned origin if that memory is tainted.
251 ChainAndWriteOriginIfTainted((uptr
)src
+ (end
- d
), (d
+ size
) - end
, end
,
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
) {
268 if (*src_o
!= last_src_o
) {
270 last_dst_o
= ChainOrigin(last_src_o
, stack
);
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
,
282 uptr end
= OriginAlignDown(d
+ size
);
284 // Copy right unaligned origin if that memory is tainted.
286 ChainAndWriteOriginIfTainted((uptr
)src
+ (end
- d
), (d
+ size
) - end
, end
,
289 uptr beg
= OriginAlignDown(d
);
291 if (beg
+ kOriginAlign
< end
) {
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
) {
304 if (*src_end_o
!= last_src_o
) {
305 last_src_o
= *src_end_o
;
306 last_dst_o
= ChainOrigin(last_src_o
, stack
);
312 // Copy left unaligned origin if that memory is tainted.
314 ChainAndWriteOriginIfTainted((uptr
)src
, beg
+ kOriginAlign
- d
, beg
, stack
);
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
321 static void MoveOrigin(const void *dst
, const void *src
, uptr size
,
323 // Validate address regions.
324 if (!MEM_IS_SHADOW(shadow_for(dst
)) ||
325 !MEM_IS_SHADOW(shadow_for((void *)((uptr
)dst
+ size
))) ||
326 !MEM_IS_SHADOW(shadow_for(src
)) ||
327 !MEM_IS_SHADOW(shadow_for((void *)((uptr
)src
+ size
)))) {
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
= OriginAlignDown((uptr
)src
);
336 uptr src_aligned_end
= OriginAlignDown((uptr
)src
+ size
);
337 uptr dst_aligned_beg
= OriginAlignDown((uptr
)dst
);
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
);
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
) {
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
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.
358 if (*(u32
*)beg
!= origin
)
359 *(u32
*)beg
= origin
;
362 for (uptr addr
= beg
; addr
< (end
& ~7UL); addr
+= 8) {
363 if (*(u64
*)addr
== origin64
)
365 *(u64
*)addr
= origin64
;
368 if (*(u32
*)(end
- kOriginAlign
) != origin
)
369 *(u32
*)(end
- kOriginAlign
) = origin
;
372 #define RET_CHAIN_ORIGIN(id) \
373 GET_CALLER_PC_BP_SP; \
375 GET_STORE_STACK_TRACE_PC_BP(pc, bp); \
376 return ChainOrigin(id, &stack);
378 // Return a new origin chain with the previous ID id and the current stack
380 extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
381 __dfsan_chain_origin(dfsan_origin id
) {
385 // Return a new origin chain with the previous ID id and the current stack
386 // trace if the label is tainted.
387 extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
388 __dfsan_chain_origin_if_tainted(dfsan_label label
, dfsan_origin id
) {
394 // Copy or move the origins of the len bytes from src to dst.
395 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void __dfsan_mem_origin_transfer(
396 const void *dst
, const void *src
, uptr len
) {
400 GET_STORE_STACK_TRACE_PC_BP(pc
, bp
);
401 MoveOrigin(dst
, src
, len
, &stack
);
404 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void dfsan_mem_origin_transfer(
405 const void *dst
, const void *src
, uptr len
) {
406 __dfsan_mem_origin_transfer(dst
, src
, len
);
409 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void dfsan_mem_shadow_transfer(
410 void *dst
, const void *src
, uptr len
) {
411 internal_memcpy((void *)__dfsan::shadow_for(dst
),
412 (const void *)__dfsan::shadow_for(src
),
413 len
* sizeof(dfsan_label
));
418 bool dfsan_inited
= false;
419 bool dfsan_init_is_running
= false;
421 void dfsan_copy_memory(void *dst
, const void *src
, uptr size
) {
422 internal_memcpy(dst
, src
, size
);
423 dfsan_mem_shadow_transfer(dst
, src
, size
);
424 if (dfsan_get_track_origins())
425 dfsan_mem_origin_transfer(dst
, src
, size
);
428 // Releases the pages within the origin address range.
429 static void ReleaseOrigins(void *addr
, uptr size
) {
430 const uptr beg_origin_addr
= (uptr
)__dfsan::origin_for(addr
);
431 const void *end_addr
= (void *)((uptr
)addr
+ size
);
432 const uptr end_origin_addr
= (uptr
)__dfsan::origin_for(end_addr
);
434 if (end_origin_addr
- beg_origin_addr
<
435 common_flags()->clear_shadow_mmap_threshold
)
438 const uptr page_size
= GetPageSizeCached();
439 const uptr beg_aligned
= RoundUpTo(beg_origin_addr
, page_size
);
440 const uptr end_aligned
= RoundDownTo(end_origin_addr
, page_size
);
442 if (!MmapFixedSuperNoReserve(beg_aligned
, end_aligned
- beg_aligned
))
446 static void WriteZeroShadowInRange(uptr beg
, uptr end
) {
447 // Don't write the label if it is already the value we need it to be.
448 // In a program where most addresses are not labeled, it is common that
449 // a page of shadow memory is entirely zeroed. The Linux copy-on-write
450 // implementation will share all of the zeroed pages, making a copy of a
451 // page when any value is written. The un-sharing will happen even if
452 // the value written does not change the value in memory. Avoiding the
453 // write when both |label| and |*labelp| are zero dramatically reduces
454 // the amount of real memory used by large programs.
455 if (!mem_is_zero((const char *)beg
, end
- beg
))
456 internal_memset((void *)beg
, 0, end
- beg
);
459 // Releases the pages within the shadow address range, and sets
460 // the shadow addresses not on the pages to be 0.
461 static void ReleaseOrClearShadows(void *addr
, uptr size
) {
462 const uptr beg_shadow_addr
= (uptr
)__dfsan::shadow_for(addr
);
463 const void *end_addr
= (void *)((uptr
)addr
+ size
);
464 const uptr end_shadow_addr
= (uptr
)__dfsan::shadow_for(end_addr
);
466 if (end_shadow_addr
- beg_shadow_addr
<
467 common_flags()->clear_shadow_mmap_threshold
) {
468 WriteZeroShadowInRange(beg_shadow_addr
, end_shadow_addr
);
472 const uptr page_size
= GetPageSizeCached();
473 const uptr beg_aligned
= RoundUpTo(beg_shadow_addr
, page_size
);
474 const uptr end_aligned
= RoundDownTo(end_shadow_addr
, page_size
);
476 if (beg_aligned
>= end_aligned
) {
477 WriteZeroShadowInRange(beg_shadow_addr
, end_shadow_addr
);
479 if (beg_aligned
!= beg_shadow_addr
)
480 WriteZeroShadowInRange(beg_shadow_addr
, beg_aligned
);
481 if (end_aligned
!= end_shadow_addr
)
482 WriteZeroShadowInRange(end_aligned
, end_shadow_addr
);
483 if (!MmapFixedSuperNoReserve(beg_aligned
, end_aligned
- beg_aligned
))
488 void SetShadow(dfsan_label label
, void *addr
, uptr size
, dfsan_origin origin
) {
490 const uptr beg_shadow_addr
= (uptr
)__dfsan::shadow_for(addr
);
491 internal_memset((void *)beg_shadow_addr
, label
, size
);
492 if (dfsan_get_track_origins())
493 SetOrigin(addr
, size
, origin
);
497 if (dfsan_get_track_origins())
498 ReleaseOrigins(addr
, size
);
500 ReleaseOrClearShadows(addr
, size
);
503 } // namespace __dfsan
505 // If the label s is tainted, set the size bytes from the address p to be a new
506 // origin chain with the previous ID o and the current stack trace. This is
507 // used by instrumentation to reduce code size when too much code is inserted.
508 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void __dfsan_maybe_store_origin(
509 dfsan_label s
, void *p
, uptr size
, dfsan_origin o
) {
513 GET_STORE_STACK_TRACE_PC_BP(pc
, bp
);
514 SetOrigin(p
, size
, ChainOrigin(o
, &stack
));
518 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void __dfsan_set_label(
519 dfsan_label label
, dfsan_origin origin
, void *addr
, uptr size
) {
520 __dfsan::SetShadow(label
, addr
, size
, origin
);
523 SANITIZER_INTERFACE_ATTRIBUTE
524 void dfsan_set_label(dfsan_label label
, void *addr
, uptr size
) {
525 dfsan_origin init_origin
= 0;
526 if (label
&& dfsan_get_track_origins()) {
528 GET_STORE_STACK_TRACE_PC_BP(pc
, bp
);
529 init_origin
= ChainOrigin(0, &stack
, true);
531 __dfsan::SetShadow(label
, addr
, size
, init_origin
);
534 SANITIZER_INTERFACE_ATTRIBUTE
535 void dfsan_add_label(dfsan_label label
, void *addr
, uptr size
) {
539 if (dfsan_get_track_origins()) {
541 GET_STORE_STACK_TRACE_PC_BP(pc
, bp
);
542 dfsan_origin init_origin
= ChainOrigin(0, &stack
, true);
543 SetOrigin(addr
, size
, init_origin
);
546 for (dfsan_label
*labelp
= shadow_for(addr
); size
!= 0; --size
, ++labelp
)
550 // Unlike the other dfsan interface functions the behavior of this function
551 // depends on the label of one of its arguments. Hence it is implemented as a
553 extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
554 __dfsw_dfsan_get_label(long data
, dfsan_label data_label
,
555 dfsan_label
*ret_label
) {
560 extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
__dfso_dfsan_get_label(
561 long data
, dfsan_label data_label
, dfsan_label
*ret_label
,
562 dfsan_origin data_origin
, dfsan_origin
*ret_origin
) {
568 // This function is used if dfsan_get_origin is called when origin tracking is
570 extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
__dfsw_dfsan_get_origin(
571 long data
, dfsan_label data_label
, dfsan_label
*ret_label
) {
576 extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
__dfso_dfsan_get_origin(
577 long data
, dfsan_label data_label
, dfsan_label
*ret_label
,
578 dfsan_origin data_origin
, dfsan_origin
*ret_origin
) {
584 SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
585 dfsan_read_label(const void *addr
, uptr size
) {
588 return __dfsan_union_load(shadow_for(addr
), size
);
591 SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
592 dfsan_read_origin_of_first_taint(const void *addr
, uptr size
) {
593 return GetOriginIfTainted((uptr
)addr
, size
);
596 SANITIZER_INTERFACE_ATTRIBUTE
void dfsan_set_label_origin(dfsan_label label
,
600 __dfsan_set_label(label
, origin
, addr
, size
);
603 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
int
604 dfsan_has_label(dfsan_label label
, dfsan_label elem
) {
605 return (label
& elem
) == elem
;
610 typedef void (*dfsan_conditional_callback_t
)(dfsan_label label
,
611 dfsan_origin origin
);
612 static dfsan_conditional_callback_t conditional_callback
= nullptr;
613 static dfsan_label labels_in_signal_conditional
= 0;
615 static void ConditionalCallback(dfsan_label label
, dfsan_origin origin
) {
616 // Programs have many branches. For efficiency the conditional sink callback
617 // handler needs to ignore as many as possible as early as possible.
621 if (conditional_callback
== nullptr) {
625 // This initial ConditionalCallback handler needs to be in here in dfsan
626 // runtime (rather than being an entirely user implemented hook) so that it
627 // has access to dfsan thread information.
628 DFsanThread
*t
= GetCurrentThread();
629 // A callback operation which does useful work (like record the flow) will
630 // likely be too long executed in a signal handler.
631 if (t
&& t
->InSignalHandler()) {
632 // Record set of labels used in signal handler for completeness.
633 labels_in_signal_conditional
|= label
;
637 conditional_callback(label
, origin
);
640 } // namespace __dfsan
642 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void
643 __dfsan_conditional_callback_origin(dfsan_label label
, dfsan_origin origin
) {
644 __dfsan::ConditionalCallback(label
, origin
);
647 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void __dfsan_conditional_callback(
649 __dfsan::ConditionalCallback(label
, 0);
652 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void dfsan_set_conditional_callback(
653 __dfsan::dfsan_conditional_callback_t callback
) {
654 __dfsan::conditional_callback
= callback
;
657 extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label
658 dfsan_get_labels_in_signal_conditional() {
659 return __dfsan::labels_in_signal_conditional
;
662 class Decorator
: public __sanitizer::SanitizerCommonDecorator
{
664 Decorator() : SanitizerCommonDecorator() {}
665 const char *Origin() const { return Magenta(); }
670 void PrintNoOriginTrackingWarning() {
673 " %sDFSan: origin tracking is not enabled. Did you specify the "
674 "-dfsan-track-origins=1 option?%s\n",
675 d
.Warning(), d
.Default());
678 void PrintNoTaintWarning(const void *address
) {
680 Printf(" %sDFSan: no tainted value at %x%s\n", d
.Warning(), address
,
684 void PrintInvalidOriginWarning(dfsan_label label
, const void *address
) {
687 " %sTaint value 0x%x (at %p) has invalid origin tracking. This can "
688 "be a DFSan bug.%s\n",
689 d
.Warning(), label
, address
, d
.Default());
692 void PrintInvalidOriginIdWarning(dfsan_origin origin
) {
695 " %sOrigin Id %d has invalid origin tracking. This can "
696 "be a DFSan bug.%s\n",
697 d
.Warning(), origin
, d
.Default());
700 bool PrintOriginTraceFramesToStr(Origin o
, InternalScopedString
*out
) {
704 while (o
.isChainedOrigin()) {
706 dfsan_origin origin_id
= o
.raw_id();
707 o
= o
.getNextChainedOrigin(&stack
);
708 if (o
.isChainedOrigin())
710 " %sOrigin value: 0x%x, Taint value was stored to memory at%s\n",
711 d
.Origin(), origin_id
, d
.Default());
713 out
->append(" %sOrigin value: 0x%x, Taint value was created at%s\n",
714 d
.Origin(), origin_id
, d
.Default());
716 // Includes a trailing newline, so no need to add it again.
724 bool PrintOriginTraceToStr(const void *addr
, const char *description
,
725 InternalScopedString
*out
) {
727 CHECK(dfsan_get_track_origins());
730 const dfsan_label label
= *__dfsan::shadow_for(addr
);
733 const dfsan_origin origin
= *__dfsan::origin_for(addr
);
735 out
->append(" %sTaint value 0x%x (at %p) origin tracking (%s)%s\n",
736 d
.Origin(), label
, addr
, description
? description
: "",
739 Origin o
= Origin::FromRawId(origin
);
740 return PrintOriginTraceFramesToStr(o
, out
);
745 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void dfsan_print_origin_trace(
746 const void *addr
, const char *description
) {
747 if (!dfsan_get_track_origins()) {
748 PrintNoOriginTrackingWarning();
752 const dfsan_label label
= *__dfsan::shadow_for(addr
);
754 PrintNoTaintWarning(addr
);
758 InternalScopedString trace
;
759 bool success
= PrintOriginTraceToStr(addr
, description
, &trace
);
762 Printf("%s", trace
.data());
765 PrintInvalidOriginWarning(label
, addr
);
768 extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr
769 dfsan_sprint_origin_trace(const void *addr
, const char *description
,
770 char *out_buf
, uptr out_buf_size
) {
773 if (!dfsan_get_track_origins()) {
774 PrintNoOriginTrackingWarning();
778 const dfsan_label label
= *__dfsan::shadow_for(addr
);
780 PrintNoTaintWarning(addr
);
784 InternalScopedString trace
;
785 bool success
= PrintOriginTraceToStr(addr
, description
, &trace
);
788 PrintInvalidOriginWarning(label
, addr
);
793 internal_strncpy(out_buf
, trace
.data(), out_buf_size
- 1);
794 out_buf
[out_buf_size
- 1] = '\0';
797 return trace
.length();
800 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void dfsan_print_origin_id_trace(
801 dfsan_origin origin
) {
802 if (!dfsan_get_track_origins()) {
803 PrintNoOriginTrackingWarning();
806 Origin o
= Origin::FromRawId(origin
);
808 InternalScopedString trace
;
809 bool success
= PrintOriginTraceFramesToStr(o
, &trace
);
812 Printf("%s", trace
.data());
815 PrintInvalidOriginIdWarning(origin
);
818 extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr
dfsan_sprint_origin_id_trace(
819 dfsan_origin origin
, char *out_buf
, uptr out_buf_size
) {
822 if (!dfsan_get_track_origins()) {
823 PrintNoOriginTrackingWarning();
826 Origin o
= Origin::FromRawId(origin
);
828 InternalScopedString trace
;
829 bool success
= PrintOriginTraceFramesToStr(o
, &trace
);
832 PrintInvalidOriginIdWarning(origin
);
837 internal_strncpy(out_buf
, trace
.data(), out_buf_size
- 1);
838 out_buf
[out_buf_size
- 1] = '\0';
841 return trace
.length();
844 extern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_origin
845 dfsan_get_init_origin(const void *addr
) {
846 if (!dfsan_get_track_origins())
849 const dfsan_label label
= *__dfsan::shadow_for(addr
);
853 const dfsan_origin origin
= *__dfsan::origin_for(addr
);
855 Origin o
= Origin::FromRawId(origin
);
856 dfsan_origin origin_id
= o
.raw_id();
857 while (o
.isChainedOrigin()) {
859 origin_id
= o
.raw_id();
860 o
= o
.getNextChainedOrigin(&stack
);
865 void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc
, uptr bp
,
869 using namespace __dfsan
;
870 DFsanThread
*t
= GetCurrentThread();
871 if (!t
|| !StackTrace::WillUseFastUnwind(request_fast
)) {
872 return Unwind(max_depth
, pc
, bp
, context
, 0, 0, false);
874 Unwind(max_depth
, pc
, bp
, nullptr, t
->stack_top(), t
->stack_bottom(), true);
877 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void __sanitizer_print_stack_trace() {
879 GET_STORE_STACK_TRACE_PC_BP(pc
, bp
);
883 extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr
884 dfsan_sprint_stack_trace(char *out_buf
, uptr out_buf_size
) {
887 GET_STORE_STACK_TRACE_PC_BP(pc
, bp
);
888 return stack
.PrintTo(out_buf
, out_buf_size
);
891 void Flags::SetDefaults() {
892 #define DFSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
893 #include "dfsan_flags.inc"
897 static void RegisterDfsanFlags(FlagParser
*parser
, Flags
*f
) {
898 #define DFSAN_FLAG(Type, Name, DefaultValue, Description) \
899 RegisterFlag(parser, #Name, Description, &f->Name);
900 #include "dfsan_flags.inc"
904 static void InitializeFlags() {
905 SetCommonFlagsDefaults();
908 cf
.CopyFrom(*common_flags());
909 cf
.intercept_tls_get_addr
= true;
910 OverrideCommonFlags(cf
);
912 flags().SetDefaults();
915 RegisterCommonFlags(&parser
);
916 RegisterDfsanFlags(&parser
, &flags());
917 parser
.ParseStringFromEnv("DFSAN_OPTIONS");
918 InitializeCommonFlags();
919 if (Verbosity()) ReportUnrecognizedFlags();
920 if (common_flags()->help
) parser
.PrintFlagDescriptions();
923 SANITIZER_INTERFACE_ATTRIBUTE
924 void dfsan_clear_arg_tls(uptr offset
, uptr size
) {
925 internal_memset((void *)((uptr
)__dfsan_arg_tls
+ offset
), 0, size
);
928 SANITIZER_INTERFACE_ATTRIBUTE
929 void dfsan_clear_thread_local_state() {
930 internal_memset(__dfsan_arg_tls
, 0, sizeof(__dfsan_arg_tls
));
931 internal_memset(__dfsan_retval_tls
, 0, sizeof(__dfsan_retval_tls
));
933 if (dfsan_get_track_origins()) {
934 internal_memset(__dfsan_arg_origin_tls
, 0, sizeof(__dfsan_arg_origin_tls
));
935 internal_memset(&__dfsan_retval_origin_tls
, 0,
936 sizeof(__dfsan_retval_origin_tls
));
940 SANITIZER_INTERFACE_ATTRIBUTE
941 void dfsan_set_arg_tls(uptr offset
, dfsan_label label
) {
942 // 2x to match ShadowTLSAlignment.
943 // ShadowTLSAlignment should probably be changed.
944 // TODO: Consider reducing ShadowTLSAlignment to 1.
945 // Aligning to 2 bytes is probably a remnant of fast16 mode.
946 ((dfsan_label
*)__dfsan_arg_tls
)[offset
* 2] = label
;
949 SANITIZER_INTERFACE_ATTRIBUTE
950 void dfsan_set_arg_origin_tls(uptr offset
, dfsan_origin o
) {
951 __dfsan_arg_origin_tls
[offset
] = o
;
954 extern "C" void dfsan_flush() {
955 const uptr maxVirtualAddress
= GetMaxUserVirtualAddress();
956 for (unsigned i
= 0; i
< kMemoryLayoutSize
; ++i
) {
957 uptr start
= kMemoryLayout
[i
].start
;
958 uptr end
= kMemoryLayout
[i
].end
;
959 uptr size
= end
- start
;
960 MappingDesc::Type type
= kMemoryLayout
[i
].type
;
962 if (type
!= MappingDesc::SHADOW
&& type
!= MappingDesc::ORIGIN
)
965 // Check if the segment should be mapped based on platform constraints.
966 if (start
>= maxVirtualAddress
)
969 if (!MmapFixedSuperNoReserve(start
, size
, kMemoryLayout
[i
].name
)) {
970 Printf("FATAL: DataFlowSanitizer: failed to clear memory region\n");
974 __dfsan::labels_in_signal_conditional
= 0;
977 // TODO: CheckMemoryLayoutSanity is based on msan.
978 // Consider refactoring these into a shared implementation.
979 static void CheckMemoryLayoutSanity() {
981 for (unsigned i
= 0; i
< kMemoryLayoutSize
; ++i
) {
982 uptr start
= kMemoryLayout
[i
].start
;
983 uptr end
= kMemoryLayout
[i
].end
;
984 MappingDesc::Type type
= kMemoryLayout
[i
].type
;
985 CHECK_LT(start
, end
);
986 CHECK_EQ(prev_end
, start
);
987 CHECK(addr_is_type(start
, type
));
988 CHECK(addr_is_type((start
+ end
) / 2, type
));
989 CHECK(addr_is_type(end
- 1, type
));
990 if (type
== MappingDesc::APP
) {
992 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr
)));
993 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr
)));
994 CHECK_EQ(MEM_TO_ORIGIN(addr
), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr
)));
996 addr
= (start
+ end
) / 2;
997 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr
)));
998 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr
)));
999 CHECK_EQ(MEM_TO_ORIGIN(addr
), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr
)));
1002 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr
)));
1003 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr
)));
1004 CHECK_EQ(MEM_TO_ORIGIN(addr
), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr
)));
1010 // TODO: CheckMemoryRangeAvailability is based on msan.
1011 // Consider refactoring these into a shared implementation.
1012 static bool CheckMemoryRangeAvailability(uptr beg
, uptr size
) {
1014 uptr end
= beg
+ size
- 1;
1015 if (!MemoryRangeIsAvailable(beg
, end
)) {
1016 Printf("FATAL: Memory range %p - %p is not available.\n", beg
, end
);
1023 // TODO: ProtectMemoryRange is based on msan.
1024 // Consider refactoring these into a shared implementation.
1025 static bool ProtectMemoryRange(uptr beg
, uptr size
, const char *name
) {
1027 void *addr
= MmapFixedNoAccess(beg
, size
, name
);
1028 if (beg
== 0 && addr
) {
1029 // Depending on the kernel configuration, we may not be able to protect
1030 // the page at address zero.
1031 uptr gap
= 16 * GetPageSizeCached();
1034 addr
= MmapFixedNoAccess(beg
, size
, name
);
1036 if ((uptr
)addr
!= beg
) {
1037 uptr end
= beg
+ size
- 1;
1038 Printf("FATAL: Cannot protect memory range %p - %p (%s).\n", beg
, end
,
1046 // TODO: InitShadow is based on msan.
1047 // Consider refactoring these into a shared implementation.
1048 bool InitShadow(bool init_origins
) {
1049 // Let user know mapping parameters first.
1050 VPrintf(1, "dfsan_init %p\n", (void *)&__dfsan::dfsan_init
);
1051 for (unsigned i
= 0; i
< kMemoryLayoutSize
; ++i
)
1052 VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout
[i
].name
, kMemoryLayout
[i
].start
,
1053 kMemoryLayout
[i
].end
- 1);
1055 CheckMemoryLayoutSanity();
1057 if (!MEM_IS_APP(&__dfsan::dfsan_init
)) {
1058 Printf("FATAL: Code %p is out of application range. Non-PIE build?\n",
1059 (uptr
)&__dfsan::dfsan_init
);
1063 const uptr maxVirtualAddress
= GetMaxUserVirtualAddress();
1065 for (unsigned i
= 0; i
< kMemoryLayoutSize
; ++i
) {
1066 uptr start
= kMemoryLayout
[i
].start
;
1067 uptr end
= kMemoryLayout
[i
].end
;
1068 uptr size
= end
- start
;
1069 MappingDesc::Type type
= kMemoryLayout
[i
].type
;
1071 // Check if the segment should be mapped based on platform constraints.
1072 if (start
>= maxVirtualAddress
)
1075 bool map
= type
== MappingDesc::SHADOW
||
1076 (init_origins
&& type
== MappingDesc::ORIGIN
);
1077 bool protect
= type
== MappingDesc::INVALID
||
1078 (!init_origins
&& type
== MappingDesc::ORIGIN
);
1079 CHECK(!(map
&& protect
));
1080 if (!map
&& !protect
)
1081 CHECK(type
== MappingDesc::APP
);
1083 if (!CheckMemoryRangeAvailability(start
, size
))
1085 if (!MmapFixedSuperNoReserve(start
, size
, kMemoryLayout
[i
].name
))
1087 if (common_flags()->use_madv_dontdump
)
1088 DontDumpShadowMemory(start
, size
);
1091 if (!CheckMemoryRangeAvailability(start
, size
))
1093 if (!ProtectMemoryRange(start
, size
, kMemoryLayout
[i
].name
))
1101 static void DFsanInit(int argc
, char **argv
, char **envp
) {
1102 CHECK(!dfsan_init_is_running
);
1105 dfsan_init_is_running
= true;
1106 SanitizerToolName
= "DataflowSanitizer";
1108 AvoidCVE_2016_2143();
1114 InitShadow(dfsan_get_track_origins());
1116 initialize_interceptors();
1119 DFsanTSDInit(DFsanTSDDtor
);
1121 dfsan_allocator_init();
1123 DFsanThread
*main_thread
= DFsanThread::Create(nullptr, nullptr);
1124 SetCurrentThread(main_thread
);
1125 main_thread
->Init();
1127 dfsan_init_is_running
= false;
1128 dfsan_inited
= true;
1133 void dfsan_init() { DFsanInit(0, nullptr, nullptr); }
1135 } // namespace __dfsan
1137 #if SANITIZER_CAN_USE_PREINIT_ARRAY
1138 __attribute__((section(".preinit_array"),
1139 used
)) static void (*dfsan_init_ptr
)(int, char **,
1140 char **) = DFsanInit
;