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