1 //===-- hwasan_checks.h -----------------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of HWAddressSanitizer.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef HWASAN_CHECKS_H
15 #define HWASAN_CHECKS_H
16
17 #include "hwasan_mapping.h"
18
19 namespace __hwasan {
20 template <unsigned X>
SigTrap(uptr p)21 __attribute__((always_inline)) static void SigTrap(uptr p) {
22 #if defined(__aarch64__)
23 (void)p;
24 // 0x900 is added to do not interfere with the kernel use of lower values of
25 // brk immediate.
26 // FIXME: Add a constraint to put the pointer into x0, the same as x86 branch.
27 asm("brk %0\n\t" ::"n"(0x900 + X));
28 #elif defined(__x86_64__)
29 // INT3 + NOP DWORD ptr [EAX + X] to pass X to our signal handler, 5 bytes
30 // total. The pointer is passed via rdi.
31 // 0x40 is added as a safeguard, to help distinguish our trap from others and
32 // to avoid 0 offsets in the command (otherwise it'll be reduced to a
33 // different nop command, the three bytes one).
34 asm volatile(
35 "int3\n"
36 "nopl %c0(%%rax)\n" ::"n"(0x40 + X),
37 "D"(p));
38 #else
39 // FIXME: not always sigill.
40 __builtin_trap();
41 #endif
42 // __builtin_unreachable();
43 }
44
45 enum class ErrorAction { Abort, Recover };
46 enum class AccessType { Load, Store };
47
48 template <ErrorAction EA, AccessType AT, unsigned LogSize>
CheckAddress(uptr p)49 __attribute__((always_inline, nodebug)) static void CheckAddress(uptr p) {
50 tag_t ptr_tag = GetTagFromPointer(p);
51 uptr ptr_raw = p & ~kAddressTagMask;
52 tag_t mem_tag = *(tag_t *)MemToShadow(ptr_raw);
53 if (UNLIKELY(ptr_tag != mem_tag)) {
54 SigTrap<0x20 * (EA == ErrorAction::Recover) +
55 0x10 * (AT == AccessType::Store) + LogSize>(p);
56 if (EA == ErrorAction::Abort)
57 __builtin_unreachable();
58 }
59 }
60
61 template <ErrorAction EA, AccessType AT>
CheckAddressSized(uptr p,uptr sz)62 __attribute__((always_inline, nodebug)) static void CheckAddressSized(uptr p,
63 uptr sz) {
64 if (sz == 0)
65 return;
66 tag_t ptr_tag = GetTagFromPointer(p);
67 uptr ptr_raw = p & ~kAddressTagMask;
68 tag_t *shadow_first = (tag_t *)MemToShadow(ptr_raw);
69 tag_t *shadow_last = (tag_t *)MemToShadow(ptr_raw + sz - 1);
70 for (tag_t *t = shadow_first; t <= shadow_last; ++t)
71 if (UNLIKELY(ptr_tag != *t)) {
72 SigTrap<0x20 * (EA == ErrorAction::Recover) +
73 0x10 * (AT == AccessType::Store) + 0xf>(p);
74 if (EA == ErrorAction::Abort)
75 __builtin_unreachable();
76 }
77 }
78 } // end namespace __hwasan
79
80 #endif // HWASAN_CHECKS_H
81