1 | // Test fixed shadow base functionality. |
2 | // |
3 | // Default compiler instrumentation works with any shadow base (dynamic or fixed). |
4 | // RUN: %clang_hwasan %s -o %t |
5 | // RUN: %run %t |
6 | // RUN: HWASAN_OPTIONS=fixed_shadow_base=263878495698944 %run %t 2>%t.out || (cat %t.out | FileCheck %s) |
7 | // RUN: HWASAN_OPTIONS=fixed_shadow_base=4398046511104 %run %t |
8 | // |
9 | // If -hwasan-mapping-offset is set, then the fixed_shadow_base needs to match. |
10 | // RUN: %clang_hwasan %s -mllvm -hwasan-mapping-offset=263878495698944 -o %t |
11 | // RUN: HWASAN_OPTIONS=fixed_shadow_base=263878495698944 %run %t 2>%t.out || (cat %t.out | FileCheck %s) |
12 | // RUN: HWASAN_OPTIONS=fixed_shadow_base=4398046511104 not %run %t |
13 | |
14 | // RUN: %clang_hwasan %s -mllvm -hwasan-mapping-offset=4398046511104 -o %t |
15 | // RUN: HWASAN_OPTIONS=fixed_shadow_base=4398046511104 %run %t |
16 | // RUN: HWASAN_OPTIONS=fixed_shadow_base=263878495698944 not %run %t |
17 | // |
18 | // Note: if fixed_shadow_base is not set, compiler-rt will dynamically choose a |
19 | // shadow base, which has a tiny but non-zero probability of matching the |
20 | // compiler instrumentation. To avoid test flake, we do not test this case. |
21 | // |
22 | // Assume 48-bit VMA |
23 | // REQUIRES: aarch64-target-arch |
24 | // |
25 | // REQUIRES: Clang |
26 | // |
27 | // UNSUPPORTED: android |
28 | |
29 | // CHECK: FATAL: HWAddressSanitizer: Shadow range {{.*}} is not available |
30 | |
31 | #include <assert.h> |
32 | #include <sanitizer/allocator_interface.h> |
33 | #include <sanitizer/hwasan_interface.h> |
34 | #include <stdio.h> |
35 | #include <stdlib.h> |
36 | #include <sys/mman.h> |
37 | |
38 | int main() { |
39 | __hwasan_enable_allocator_tagging(); |
40 | |
41 | // We test that the compiler instrumentation is able to access shadow memory |
42 | // for many different addresses. If we only test a small number of addresses, |
43 | // it might work by chance even if the shadow base does not match between the |
44 | // compiler instrumentation and compiler-rt. |
45 | void **mmaps[256]; |
46 | // 48-bit VMA |
47 | for (int i = 0; i < 256; i++) { |
48 | unsigned long long addr = (i * (1ULL << 40)); |
49 | |
50 | void *p = mmap(addr: (void *)addr, len: 4096, PROT_READ | PROT_WRITE, |
51 | MAP_PRIVATE | MAP_ANONYMOUS, fd: -1, offset: 0); |
52 | // We don't use MAP_FIXED, to avoid overwriting critical memory. |
53 | // However, if we don't get allocated the requested address, it |
54 | // isn't a useful test. |
55 | if ((unsigned long long)p != addr) { |
56 | munmap(addr: p, len: 4096); |
57 | mmaps[i] = MAP_FAILED; |
58 | } else { |
59 | mmaps[i] = p; |
60 | } |
61 | } |
62 | |
63 | int failures = 0; |
64 | for (int i = 0; i < 256; i++) { |
65 | if (mmaps[i] == MAP_FAILED) { |
66 | failures++; |
67 | } else { |
68 | printf(format: "%d %p\n" , i, mmaps[i]); |
69 | munmap(addr: mmaps[i], len: 4096); |
70 | } |
71 | } |
72 | |
73 | // We expect roughly 17 failures: |
74 | // - the page at address zero |
75 | // - 16 failures because the shadow memory takes up 1/16th of the address space |
76 | // We could also get unlucky e.g., if libraries or binaries are loaded into the |
77 | // exact addresses where we tried to map. |
78 | // To avoid test flake, we allow some margin of error. |
79 | printf(format: "Failed: %d\n" , failures); |
80 | assert(failures < 48); |
81 | return 0; |
82 | } |
83 | |