1 //===-- hwasan_globals.cpp ------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of HWAddressSanitizer. 10 // 11 // HWAddressSanitizer globals-specific runtime. 12 //===----------------------------------------------------------------------===// 13 14 #include "hwasan_globals.h" 15 16 #include "sanitizer_common/sanitizer_array_ref.h" 17 18 namespace __hwasan { 19 20 enum { NT_LLVM_HWASAN_GLOBALS = 3 }; 21 struct hwasan_global_note { 22 s32 begin_relptr; 23 s32 end_relptr; 24 }; 25 26 // Check that the given library meets the code model requirements for tagged 27 // globals. These properties are not checked at link time so they need to be 28 // checked at runtime. 29 static void CheckCodeModel(ElfW(Addr) base, const ElfW(Phdr) * phdr, 30 ElfW(Half) phnum) { 31 ElfW(Addr) min_addr = -1ull, max_addr = 0; 32 for (unsigned i = 0; i != phnum; ++i) { 33 if (phdr[i].p_type != PT_LOAD) 34 continue; 35 ElfW(Addr) lo = base + phdr[i].p_vaddr, hi = lo + phdr[i].p_memsz; 36 if (min_addr > lo) 37 min_addr = lo; 38 if (max_addr < hi) 39 max_addr = hi; 40 } 41 42 if (max_addr - min_addr > 1ull << 32) { 43 Report("FATAL: HWAddressSanitizer: library size exceeds 2^32\n"); 44 Die(); 45 } 46 if (max_addr > 1ull << 48) { 47 Report("FATAL: HWAddressSanitizer: library loaded above address 2^48\n"); 48 Die(); 49 } 50 } 51 52 ArrayRef<const hwasan_global> HwasanGlobalsFor(ElfW(Addr) base, 53 const ElfW(Phdr) * phdr, 54 ElfW(Half) phnum) { 55 // Read the phdrs from this DSO. 56 for (unsigned i = 0; i != phnum; ++i) { 57 if (phdr[i].p_type != PT_NOTE) 58 continue; 59 60 const char *note = reinterpret_cast<const char *>(base + phdr[i].p_vaddr); 61 const char *nend = note + phdr[i].p_memsz; 62 63 // Traverse all the notes until we find a HWASan note. 64 while (note < nend) { 65 auto *nhdr = reinterpret_cast<const ElfW(Nhdr) *>(note); 66 const char *name = note + sizeof(ElfW(Nhdr)); 67 const char *desc = name + RoundUpTo(nhdr->n_namesz, 4); 68 69 // Discard non-HWASan-Globals notes. 70 if (nhdr->n_type != NT_LLVM_HWASAN_GLOBALS || 71 internal_strcmp(name, "LLVM") != 0) { 72 note = desc + RoundUpTo(nhdr->n_descsz, 4); 73 continue; 74 } 75 76 // Only libraries with instrumented globals need to be checked against the 77 // code model since they use relocations that aren't checked at link time. 78 CheckCodeModel(base, phdr, phnum); 79 80 auto *global_note = reinterpret_cast<const hwasan_global_note *>(desc); 81 auto *globals_begin = reinterpret_cast<const hwasan_global *>( 82 note + global_note->begin_relptr); 83 auto *globals_end = reinterpret_cast<const hwasan_global *>( 84 note + global_note->end_relptr); 85 86 return {globals_begin, globals_end}; 87 } 88 } 89 90 return {}; 91 } 92 93 } // namespace __hwasan 94