1eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne//===-- dfsan.cc ----------------------------------------------------------===// 2eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// 3eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// The LLVM Compiler Infrastructure 4eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// 5eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// This file is distributed under the University of Illinois Open Source 6eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// License. See LICENSE.TXT for details. 7eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// 8eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne//===----------------------------------------------------------------------===// 9eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// 10eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// This file is a part of DataFlowSanitizer. 11eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// 12eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// DataFlowSanitizer runtime. This file defines the public interface to 13eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// DataFlowSanitizer as well as the definition of certain runtime functions 14eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// called automatically by the compiler (specifically the instrumentation pass 15eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// in llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp). 16eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// 17eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// The public interface is defined in include/sanitizer/dfsan_interface.h whose 18eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// functions are prefixed dfsan_ while the compiler interface functions are 19eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// prefixed __dfsan_. 20eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne//===----------------------------------------------------------------------===// 21eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 22eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne#include "sanitizer_common/sanitizer_atomic.h" 23eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne#include "sanitizer_common/sanitizer_common.h" 2478d737cfd36b57c784095db281bac8e3c500c8b6Peter Collingbourne#include "sanitizer_common/sanitizer_flags.h" 2586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_flag_parser.h" 26eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne#include "sanitizer_common/sanitizer_libc.h" 27eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 28fa9f5aef0583535f3ac1fa444f2cf62db324537ePeter Collingbourne#include "dfsan/dfsan.h" 29fa9f5aef0583535f3ac1fa444f2cf62db324537ePeter Collingbourne 30fa9f5aef0583535f3ac1fa444f2cf62db324537ePeter Collingbourneusing namespace __dfsan; 31fa9f5aef0583535f3ac1fa444f2cf62db324537ePeter Collingbourne 32eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbournetypedef atomic_uint16_t atomic_dfsan_label; 33eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbournestatic const dfsan_label kInitializingLabel = -1; 34eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 35eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbournestatic const uptr kNumLabels = 1 << (sizeof(dfsan_label) * 8); 36eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 37eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbournestatic atomic_dfsan_label __dfsan_last_label; 38eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbournestatic dfsan_label_info __dfsan_label_info[kNumLabels]; 39eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 4078d737cfd36b57c784095db281bac8e3c500c8b6Peter CollingbourneFlags __dfsan::flags_data; 4178d737cfd36b57c784095db281bac8e3c500c8b6Peter Collingbourne 42eee71ae5c1f4ce71612fac359463a54bc867abd6Peter CollingbourneSANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL dfsan_label __dfsan_retval_tls; 43eee71ae5c1f4ce71612fac359463a54bc867abd6Peter CollingbourneSANITIZER_INTERFACE_ATTRIBUTE THREADLOCAL dfsan_label __dfsan_arg_tls[64]; 44eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 45799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga NainarSANITIZER_INTERFACE_ATTRIBUTE uptr __dfsan_shadow_ptr_mask; 46799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 47eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// On Linux/x86_64, memory is laid out as follows: 48eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// 49eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// +--------------------+ 0x800000000000 (top of memory) 50eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// | application memory | 51eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// +--------------------+ 0x700000008000 (kAppAddr) 52eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// | | 53eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// | unused | 54eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// | | 55eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// +--------------------+ 0x200200000000 (kUnusedAddr) 56eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// | union table | 57eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// +--------------------+ 0x200000000000 (kUnionTableAddr) 58eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// | shadow memory | 59eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// +--------------------+ 0x000000010000 (kShadowAddr) 60eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// | reserved by kernel | 61eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// +--------------------+ 0x000000000000 62eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// 63eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// To derive a shadow memory address from an application memory address, 64eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// bits 44-46 are cleared to bring the address into the range 65eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// [0x000000008000,0x100000000000). Then the address is shifted left by 1 to 66eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// account for the double byte representation of shadow labels and move the 67eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// address into the shadow memory range. See the function shadow_for below. 68eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 6986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// On Linux/MIPS64, memory is laid out as follows: 7086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// 7186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// +--------------------+ 0x10000000000 (top of memory) 7286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// | application memory | 7386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// +--------------------+ 0xF000008000 (kAppAddr) 7486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// | | 7586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// | unused | 7686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// | | 7786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// +--------------------+ 0x2200000000 (kUnusedAddr) 7886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// | union table | 7986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// +--------------------+ 0x2000000000 (kUnionTableAddr) 8086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// | shadow memory | 8186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// +--------------------+ 0x0000010000 (kShadowAddr) 8286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// | reserved by kernel | 8386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// +--------------------+ 0x0000000000 8486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 85799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// On Linux/AArch64 (39-bit VMA), memory is laid out as follow: 86799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// 87799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// +--------------------+ 0x8000000000 (top of memory) 88799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | application memory | 89799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// +--------------------+ 0x7000008000 (kAppAddr) 90799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | | 91799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | unused | 92799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | | 93799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// +--------------------+ 0x1200000000 (kUnusedAddr) 94799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | union table | 95799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// +--------------------+ 0x1000000000 (kUnionTableAddr) 96799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | shadow memory | 97799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// +--------------------+ 0x0000010000 (kShadowAddr) 98799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | reserved by kernel | 99799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// +--------------------+ 0x0000000000 100799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 101799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// On Linux/AArch64 (42-bit VMA), memory is laid out as follow: 102799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// 103799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// +--------------------+ 0x40000000000 (top of memory) 104799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | application memory | 105799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// +--------------------+ 0x3ff00008000 (kAppAddr) 106799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | | 107799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | unused | 108799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | | 109799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// +--------------------+ 0x1200000000 (kUnusedAddr) 110799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | union table | 111799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// +--------------------+ 0x8000000000 (kUnionTableAddr) 112799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | shadow memory | 113799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// +--------------------+ 0x0000010000 (kShadowAddr) 114799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// | reserved by kernel | 115799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// +--------------------+ 0x0000000000 116799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 117eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbournetypedef atomic_dfsan_label dfsan_union_table_t[kNumLabels][kNumLabels]; 118eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 119799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#ifdef DFSAN_RUNTIME_VMA 120799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// Runtime detected VMA size. 121799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarint __dfsan::vmaSize; 12286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif 123eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 124799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic uptr UnusedAddr() { 125799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return MappingArchImpl<MAPPING_UNION_TABLE_ADDR>() 126799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar + sizeof(dfsan_union_table_t); 127799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 128799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 129eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbournestatic atomic_dfsan_label *union_table(dfsan_label l1, dfsan_label l2) { 130799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return &(*(dfsan_union_table_t *) UnionTableAddr())[l1][l2]; 131eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne} 132eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 1336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// Checks we do not run out of labels. 1346d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesstatic void dfsan_check_label(dfsan_label label) { 1356d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (label == kInitializingLabel) { 1366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Report("FATAL: DataFlowSanitizer: out of labels\n"); 1376d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Die(); 1386d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 1396d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 1406d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 141eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// Resolves the union of two unequal labels. Nonequality is a precondition for 142eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne// this function (the instrumentation pass inlines the equality test). 143eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourneextern "C" SANITIZER_INTERFACE_ATTRIBUTE 144eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbournedfsan_label __dfsan_union(dfsan_label l1, dfsan_label l2) { 145eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne DCHECK_NE(l1, l2); 146eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 147eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne if (l1 == 0) 148eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne return l2; 149eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne if (l2 == 0) 150eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne return l1; 151eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 152eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne if (l1 > l2) 153eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne Swap(l1, l2); 154eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 155eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne atomic_dfsan_label *table_ent = union_table(l1, l2); 156eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // We need to deal with the case where two threads concurrently request 157eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // a union of the same pair of labels. If the table entry is uninitialized, 158eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // (i.e. 0) use a compare-exchange to set the entry to kInitializingLabel 159eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // (i.e. -1) to mark that we are initializing it. 160eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne dfsan_label label = 0; 161eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne if (atomic_compare_exchange_strong(table_ent, &label, kInitializingLabel, 162eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne memory_order_acquire)) { 163eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // Check whether l2 subsumes l1. We don't need to check whether l1 164eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // subsumes l2 because we are guaranteed here that l1 < l2, and (at least 165eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // in the cases we are interested in) a label may only subsume labels 166eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // created earlier (i.e. with a lower numerical value). 167eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne if (__dfsan_label_info[l2].l1 == l1 || 168eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne __dfsan_label_info[l2].l2 == l1) { 169eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne label = l2; 170eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne } else { 171eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne label = 172eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne atomic_fetch_add(&__dfsan_last_label, 1, memory_order_relaxed) + 1; 1736d1862363c88c183b0ed7740fca876342cf0474bStephen Hines dfsan_check_label(label); 174eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne __dfsan_label_info[label].l1 = l1; 175eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne __dfsan_label_info[label].l2 = l2; 176eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne } 177eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne atomic_store(table_ent, label, memory_order_release); 178eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne } else if (label == kInitializingLabel) { 179eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // Another thread is initializing the entry. Wait until it is finished. 180eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne do { 181eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne internal_sched_yield(); 182eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne label = atomic_load(table_ent, memory_order_acquire); 183eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne } while (label == kInitializingLabel); 184eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne } 185eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne return label; 186eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne} 187eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 188eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourneextern "C" SANITIZER_INTERFACE_ATTRIBUTE 189c85d6274d127d988539ed6a35242d3f82c4eb5bfAlexey Samsonovdfsan_label __dfsan_union_load(const dfsan_label *ls, uptr n) { 190eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne dfsan_label label = ls[0]; 191c85d6274d127d988539ed6a35242d3f82c4eb5bfAlexey Samsonov for (uptr i = 1; i != n; ++i) { 192eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne dfsan_label next_label = ls[i]; 193eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne if (label != next_label) 194eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne label = __dfsan_union(label, next_label); 195eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne } 196eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne return label; 197eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne} 198eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 199e8d20340700e0253a2b08c03391409f397eac3e3Peter Collingbourneextern "C" SANITIZER_INTERFACE_ATTRIBUTE 200e8d20340700e0253a2b08c03391409f397eac3e3Peter Collingbournevoid __dfsan_unimplemented(char *fname) { 20178d737cfd36b57c784095db281bac8e3c500c8b6Peter Collingbourne if (flags().warn_unimplemented) 20278d737cfd36b57c784095db281bac8e3c500c8b6Peter Collingbourne Report("WARNING: DataFlowSanitizer: call to uninstrumented function %s\n", 20378d737cfd36b57c784095db281bac8e3c500c8b6Peter Collingbourne fname); 204e8d20340700e0253a2b08c03391409f397eac3e3Peter Collingbourne} 205e8d20340700e0253a2b08c03391409f397eac3e3Peter Collingbourne 2062c78b04e65a7eaf5a207d6cfae8fac1d7490bcaePeter Collingbourne// Use '-mllvm -dfsan-debug-nonzero-labels' and break on this function 2072c78b04e65a7eaf5a207d6cfae8fac1d7490bcaePeter Collingbourne// to try to figure out where labels are being introduced in a nominally 2082c78b04e65a7eaf5a207d6cfae8fac1d7490bcaePeter Collingbourne// label-free program. 20978d737cfd36b57c784095db281bac8e3c500c8b6Peter Collingbourneextern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_nonzero_label() { 21078d737cfd36b57c784095db281bac8e3c500c8b6Peter Collingbourne if (flags().warn_nonzero_labels) 21178d737cfd36b57c784095db281bac8e3c500c8b6Peter Collingbourne Report("WARNING: DataFlowSanitizer: saw nonzero label\n"); 21278d737cfd36b57c784095db281bac8e3c500c8b6Peter Collingbourne} 2132c78b04e65a7eaf5a207d6cfae8fac1d7490bcaePeter Collingbourne 2146d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// Indirect call to an uninstrumented vararg function. We don't have a way of 2156d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// handling these at the moment. 2166d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesextern "C" SANITIZER_INTERFACE_ATTRIBUTE void 2176d1862363c88c183b0ed7740fca876342cf0474bStephen Hines__dfsan_vararg_wrapper(const char *fname) { 2186d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Report("FATAL: DataFlowSanitizer: unsupported indirect call to vararg " 2196d1862363c88c183b0ed7740fca876342cf0474bStephen Hines "function %s\n", fname); 2206d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Die(); 2216d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 2226d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 223249cdca5989af3b55e42460283ca63096aeddfebPeter Collingbourne// Like __dfsan_union, but for use from the client or custom functions. Hence 224249cdca5989af3b55e42460283ca63096aeddfebPeter Collingbourne// the equality comparison is done here before calling __dfsan_union. 225249cdca5989af3b55e42460283ca63096aeddfebPeter CollingbourneSANITIZER_INTERFACE_ATTRIBUTE dfsan_label 226249cdca5989af3b55e42460283ca63096aeddfebPeter Collingbournedfsan_union(dfsan_label l1, dfsan_label l2) { 227249cdca5989af3b55e42460283ca63096aeddfebPeter Collingbourne if (l1 == l2) 228249cdca5989af3b55e42460283ca63096aeddfebPeter Collingbourne return l1; 229249cdca5989af3b55e42460283ca63096aeddfebPeter Collingbourne return __dfsan_union(l1, l2); 230249cdca5989af3b55e42460283ca63096aeddfebPeter Collingbourne} 231249cdca5989af3b55e42460283ca63096aeddfebPeter Collingbourne 232c85d6274d127d988539ed6a35242d3f82c4eb5bfAlexey Samsonovextern "C" SANITIZER_INTERFACE_ATTRIBUTE 233eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbournedfsan_label dfsan_create_label(const char *desc, void *userdata) { 234eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne dfsan_label label = 235eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne atomic_fetch_add(&__dfsan_last_label, 1, memory_order_relaxed) + 1; 2366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines dfsan_check_label(label); 237eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne __dfsan_label_info[label].l1 = __dfsan_label_info[label].l2 = 0; 238eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne __dfsan_label_info[label].desc = desc; 239eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne __dfsan_label_info[label].userdata = userdata; 240eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne return label; 241eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne} 242eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 243369ffffa48cb611a63dc5c7926e5c00181b14ba1Peter Collingbourneextern "C" SANITIZER_INTERFACE_ATTRIBUTE 244c85d6274d127d988539ed6a35242d3f82c4eb5bfAlexey Samsonovvoid __dfsan_set_label(dfsan_label label, void *addr, uptr size) { 2456d1862363c88c183b0ed7740fca876342cf0474bStephen Hines for (dfsan_label *labelp = shadow_for(addr); size != 0; --size, ++labelp) { 2466d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // Don't write the label if it is already the value we need it to be. 2476d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // In a program where most addresses are not labeled, it is common that 2486d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // a page of shadow memory is entirely zeroed. The Linux copy-on-write 2496d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // implementation will share all of the zeroed pages, making a copy of a 2506d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // page when any value is written. The un-sharing will happen even if 2516d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // the value written does not change the value in memory. Avoiding the 2526d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // write when both |label| and |*labelp| are zero dramatically reduces 2536d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // the amount of real memory used by large programs. 2546d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (label == *labelp) 2556d1862363c88c183b0ed7740fca876342cf0474bStephen Hines continue; 2566d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 257eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne *labelp = label; 2586d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 259eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne} 260eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 261eee71ae5c1f4ce71612fac359463a54bc867abd6Peter CollingbourneSANITIZER_INTERFACE_ATTRIBUTE 262c85d6274d127d988539ed6a35242d3f82c4eb5bfAlexey Samsonovvoid dfsan_set_label(dfsan_label label, void *addr, uptr size) { 263369ffffa48cb611a63dc5c7926e5c00181b14ba1Peter Collingbourne __dfsan_set_label(label, addr, size); 264369ffffa48cb611a63dc5c7926e5c00181b14ba1Peter Collingbourne} 265369ffffa48cb611a63dc5c7926e5c00181b14ba1Peter Collingbourne 266369ffffa48cb611a63dc5c7926e5c00181b14ba1Peter CollingbourneSANITIZER_INTERFACE_ATTRIBUTE 267c85d6274d127d988539ed6a35242d3f82c4eb5bfAlexey Samsonovvoid dfsan_add_label(dfsan_label label, void *addr, uptr size) { 268eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne for (dfsan_label *labelp = shadow_for(addr); size != 0; --size, ++labelp) 269eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne if (*labelp != label) 270eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne *labelp = __dfsan_union(*labelp, label); 271eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne} 272eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 273e8d20340700e0253a2b08c03391409f397eac3e3Peter Collingbourne// Unlike the other dfsan interface functions the behavior of this function 274e8d20340700e0253a2b08c03391409f397eac3e3Peter Collingbourne// depends on the label of one of its arguments. Hence it is implemented as a 275e8d20340700e0253a2b08c03391409f397eac3e3Peter Collingbourne// custom function. 276e8d20340700e0253a2b08c03391409f397eac3e3Peter Collingbourneextern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label 277e8d20340700e0253a2b08c03391409f397eac3e3Peter Collingbourne__dfsw_dfsan_get_label(long data, dfsan_label data_label, 278e8d20340700e0253a2b08c03391409f397eac3e3Peter Collingbourne dfsan_label *ret_label) { 279e8d20340700e0253a2b08c03391409f397eac3e3Peter Collingbourne *ret_label = 0; 280e8d20340700e0253a2b08c03391409f397eac3e3Peter Collingbourne return data_label; 281eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne} 282eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 2831528c6cea4593ac7c45d72a74efae4be36ec52f0Peter CollingbourneSANITIZER_INTERFACE_ATTRIBUTE dfsan_label 284c85d6274d127d988539ed6a35242d3f82c4eb5bfAlexey Samsonovdfsan_read_label(const void *addr, uptr size) { 2851528c6cea4593ac7c45d72a74efae4be36ec52f0Peter Collingbourne if (size == 0) 2861528c6cea4593ac7c45d72a74efae4be36ec52f0Peter Collingbourne return 0; 2871528c6cea4593ac7c45d72a74efae4be36ec52f0Peter Collingbourne return __dfsan_union_load(shadow_for(addr), size); 2881528c6cea4593ac7c45d72a74efae4be36ec52f0Peter Collingbourne} 2891528c6cea4593ac7c45d72a74efae4be36ec52f0Peter Collingbourne 29086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesextern "C" SANITIZER_INTERFACE_ATTRIBUTE 291eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourneconst struct dfsan_label_info *dfsan_get_label_info(dfsan_label label) { 292eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne return &__dfsan_label_info[label]; 293eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne} 294eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 295c85d6274d127d988539ed6a35242d3f82c4eb5bfAlexey Samsonovextern "C" SANITIZER_INTERFACE_ATTRIBUTE int 296c85d6274d127d988539ed6a35242d3f82c4eb5bfAlexey Samsonovdfsan_has_label(dfsan_label label, dfsan_label elem) { 297eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne if (label == elem) 298eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne return true; 299eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne const dfsan_label_info *info = dfsan_get_label_info(label); 300eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne if (info->l1 != 0) { 301eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne return dfsan_has_label(info->l1, elem) || dfsan_has_label(info->l2, elem); 302eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne } else { 303eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne return false; 304eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne } 305eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne} 306eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 307c85d6274d127d988539ed6a35242d3f82c4eb5bfAlexey Samsonovextern "C" SANITIZER_INTERFACE_ATTRIBUTE dfsan_label 308c85d6274d127d988539ed6a35242d3f82c4eb5bfAlexey Samsonovdfsan_has_label_with_desc(dfsan_label label, const char *desc) { 309eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne const dfsan_label_info *info = dfsan_get_label_info(label); 310eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne if (info->l1 != 0) { 311eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne return dfsan_has_label_with_desc(info->l1, desc) || 312eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne dfsan_has_label_with_desc(info->l2, desc); 313eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne } else { 314eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne return internal_strcmp(desc, info->desc) == 0; 315eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne } 316eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne} 317eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 3182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr 3192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesdfsan_get_label_count(void) { 3202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines dfsan_label max_label_allocated = 3212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines atomic_load(&__dfsan_last_label, memory_order_relaxed); 3222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 3232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return static_cast<uptr>(max_label_allocated); 3242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 3252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 3266d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesextern "C" SANITIZER_INTERFACE_ATTRIBUTE void 3276d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesdfsan_dump_labels(int fd) { 3286d1862363c88c183b0ed7740fca876342cf0474bStephen Hines dfsan_label last_label = 3296d1862363c88c183b0ed7740fca876342cf0474bStephen Hines atomic_load(&__dfsan_last_label, memory_order_relaxed); 3306d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 3316d1862363c88c183b0ed7740fca876342cf0474bStephen Hines for (uptr l = 1; l <= last_label; ++l) { 3326d1862363c88c183b0ed7740fca876342cf0474bStephen Hines char buf[64]; 3336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines internal_snprintf(buf, sizeof(buf), "%u %u %u ", l, 3346d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __dfsan_label_info[l].l1, __dfsan_label_info[l].l2); 335259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar WriteToFile(fd, buf, internal_strlen(buf)); 3366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (__dfsan_label_info[l].l1 == 0 && __dfsan_label_info[l].desc) { 337259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar WriteToFile(fd, __dfsan_label_info[l].desc, 338259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar internal_strlen(__dfsan_label_info[l].desc)); 3396d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 340259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar WriteToFile(fd, "\n", 1); 3416d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 3426d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 3436d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 34486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid Flags::SetDefaults() { 34586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define DFSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 34686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "dfsan_flags.inc" 34786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#undef DFSAN_FLAG 34886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 34986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines 35086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void RegisterDfsanFlags(FlagParser *parser, Flags *f) { 35186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#define DFSAN_FLAG(Type, Name, DefaultValue, Description) \ 35286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines RegisterFlag(parser, #Name, Description, &f->Name); 35386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "dfsan_flags.inc" 35486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#undef DFSAN_FLAG 35586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines} 35678d737cfd36b57c784095db281bac8e3c500c8b6Peter Collingbourne 35786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic void InitializeFlags() { 358799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar SetCommonFlagsDefaults(); 359799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar flags().SetDefaults(); 360799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 36186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines FlagParser parser; 362799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar RegisterCommonFlags(&parser); 36386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines RegisterDfsanFlags(&parser, &flags()); 36486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines parser.ParseString(GetEnv("DFSAN_OPTIONS")); 365c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar InitializeCommonFlags(); 366799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (Verbosity()) ReportUnrecognizedFlags(); 367799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (common_flags()->help) parser.PrintFlagDescriptions(); 368799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 369799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 370799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic void InitializePlatformEarly() { 371c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar AvoidCVE_2016_2143(); 372799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#ifdef DFSAN_RUNTIME_VMA 373799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar __dfsan::vmaSize = 374799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); 375799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (__dfsan::vmaSize == 39 || __dfsan::vmaSize == 42) { 376799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar __dfsan_shadow_ptr_mask = ShadowMask(); 377799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } else { 378799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Printf("FATAL: DataFlowSanitizer: unsupported VMA range\n"); 379799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Printf("FATAL: Found %d - Supported 39 and 42\n", __dfsan::vmaSize); 380799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Die(); 381799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 382799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif 3836d1862363c88c183b0ed7740fca876342cf0474bStephen Hines} 3846d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 3856d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesstatic void dfsan_fini() { 3866d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (internal_strcmp(flags().dump_labels_at_exit, "") != 0) { 3877c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar fd_t fd = OpenFile(flags().dump_labels_at_exit, WrOnly); 3886d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (fd == kInvalidFd) { 3896d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Report("WARNING: DataFlowSanitizer: unable to open output file %s\n", 3906d1862363c88c183b0ed7740fca876342cf0474bStephen Hines flags().dump_labels_at_exit); 3916d1862363c88c183b0ed7740fca876342cf0474bStephen Hines return; 3926d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 3936d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 3946d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Report("INFO: DataFlowSanitizer: dumping labels to %s\n", 3956d1862363c88c183b0ed7740fca876342cf0474bStephen Hines flags().dump_labels_at_exit); 3966d1862363c88c183b0ed7740fca876342cf0474bStephen Hines dfsan_dump_labels(fd); 397259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar CloseFile(fd); 3986d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 39978d737cfd36b57c784095db281bac8e3c500c8b6Peter Collingbourne} 40078d737cfd36b57c784095db281bac8e3c500c8b6Peter Collingbourne 401eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbournestatic void dfsan_init(int argc, char **argv, char **envp) { 402799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar InitializeFlags(); 403799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 404799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar InitializePlatformEarly(); 405799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 406799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar MmapFixedNoReserve(ShadowAddr(), UnusedAddr() - ShadowAddr()); 407eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 408eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // Protect the region of memory we don't use, to preserve the one-to-one 409eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // mapping from application to shadow memory. But if ASLR is disabled, Linux 410eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // will load our executable in the middle of our unused region. This mostly 411eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // works so long as the program doesn't use too much memory. We support this 412eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne // case by disabling memory protection when ASLR is disabled. 413eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne uptr init_addr = (uptr)&dfsan_init; 414799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (!(init_addr >= UnusedAddr() && init_addr < AppAddr())) 415c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar MmapFixedNoAccess(UnusedAddr(), AppAddr() - UnusedAddr()); 4166e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne 4176e4c46dc162803cc99c2a5e068fc28adb873a431Peter Collingbourne InitializeInterceptors(); 4186d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 4196d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // Register the fini callback to run when the program terminates successfully 4206d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // or it is killed by the runtime. 4216d1862363c88c183b0ed7740fca876342cf0474bStephen Hines Atexit(dfsan_fini); 422799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar AddDieCallback(dfsan_fini); 4236d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 4246d1862363c88c183b0ed7740fca876342cf0474bStephen Hines __dfsan_label_info[kInitializingLabel].desc = "<init label>"; 425eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne} 426eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne 427799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_CAN_USE_PREINIT_ARRAY 428eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne__attribute__((section(".preinit_array"), used)) 429eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbournestatic void (*dfsan_init_ptr)(int, char **, char **) = dfsan_init; 430eee71ae5c1f4ce71612fac359463a54bc867abd6Peter Collingbourne#endif 431