diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2019-08-08 21:40:00 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2019-08-08 21:40:00 +0000 |
commit | 228ee15cf7c5c30461d094a22aaeeef453b324d7 (patch) | |
tree | 96940d2baa9cf6c84c78bab1bb0a428e93433748 | |
parent | ddf4f111bd336db92a0a9ae1ebc31bbd64c62511 (diff) | |
download | compiler-rt-228ee15cf7c5c30461d094a22aaeeef453b324d7.tar.gz |
hwasan: Add a code model check for tagged globals.
See D65364 for the code model requirements for tagged globals. Because
of the relocations used these requirements cannot be checked at link
time so they must be checked at runtime.
Differential Revision: https://reviews.llvm.org/D65968
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@368351 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/hwasan/hwasan.cpp | 38 |
1 files changed, 34 insertions, 4 deletions
diff --git a/lib/hwasan/hwasan.cpp b/lib/hwasan/hwasan.cpp index f0330247a..999b51183 100644 --- a/lib/hwasan/hwasan.cpp +++ b/lib/hwasan/hwasan.cpp @@ -240,13 +240,39 @@ struct hwasan_global_note { s32 end_relptr; }; +// Check that the given library meets the code model requirements for tagged +// globals. These properties are not checked at link time so they need to be +// checked at runtime. +static void CheckCodeModel(ElfW(Addr) base, const ElfW(Phdr) * phdr, + ElfW(Half) phnum) { + ElfW(Addr) min_addr = -1ull, max_addr = 0; + for (unsigned i = 0; i != phnum; ++i) { + if (phdr[i].p_type != PT_LOAD) + continue; + ElfW(Addr) lo = base + phdr[i].p_vaddr, hi = lo + phdr[i].p_memsz; + if (min_addr > lo) + min_addr = lo; + if (max_addr < hi) + max_addr = hi; + } + + if (max_addr - min_addr > 1ull << 32) { + Report("FATAL: HWAddressSanitizer: library size exceeds 2^32\n"); + Die(); + } + if (max_addr > 1ull << 48) { + Report("FATAL: HWAddressSanitizer: library loaded above address 2^48\n"); + Die(); + } +} + static void InitGlobalsFromPhdrs(ElfW(Addr) base, const ElfW(Phdr) * phdr, ElfW(Half) phnum) { - for (; phnum != 0; ++phdr, --phnum) { - if (phdr->p_type != PT_NOTE) + for (unsigned i = 0; i != phnum; ++i) { + if (phdr[i].p_type != PT_NOTE) continue; - const char *note = reinterpret_cast<const char *>(base + phdr->p_vaddr); - const char *nend = note + phdr->p_memsz; + const char *note = reinterpret_cast<const char *>(base + phdr[i].p_vaddr); + const char *nend = note + phdr[i].p_memsz; while (note < nend) { auto *nhdr = reinterpret_cast<const ElfW(Nhdr) *>(note); const char *name = note + sizeof(ElfW(Nhdr)); @@ -257,6 +283,10 @@ static void InitGlobalsFromPhdrs(ElfW(Addr) base, const ElfW(Phdr) * phdr, continue; } + // Only libraries with instrumented globals need to be checked against the + // code model since they use relocations that aren't checked at link time. + CheckCodeModel(base, phdr, phnum); + auto *global_note = reinterpret_cast<const hwasan_global_note *>(desc); auto *global_begin = reinterpret_cast<const hwasan_global *>( note + global_note->begin_relptr); |