OLD | NEW |
1 //===- subzero/runtime/szrt_asan.c - AddressSanitizer Runtime -----*- C -*-===// | 1 //===- subzero/runtime/szrt_asan.c - AddressSanitizer Runtime -----*- C -*-===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include <stdlib.h> | 25 #include <stdlib.h> |
26 #include <sys/mman.h> | 26 #include <sys/mman.h> |
27 | 27 |
28 #define RZ_SIZE (32) | 28 #define RZ_SIZE (32) |
29 #define SHADOW_SCALE_LOG2 (3) | 29 #define SHADOW_SCALE_LOG2 (3) |
30 #define SHADOW_SCALE ((size_t)1 << SHADOW_SCALE_LOG2) | 30 #define SHADOW_SCALE ((size_t)1 << SHADOW_SCALE_LOG2) |
31 | 31 |
32 // Assuming 48 bit address space on 64 bit systems | 32 // Assuming 48 bit address space on 64 bit systems |
33 #define SHADOW_LENGTH_64 (1u << (48 - SHADOW_SCALE_LOG2)) | 33 #define SHADOW_LENGTH_64 (1u << (48 - SHADOW_SCALE_LOG2)) |
34 #define SHADOW_LENGTH_32 (1u << (32 - SHADOW_SCALE_LOG2)) | 34 #define SHADOW_LENGTH_32 (1u << (32 - SHADOW_SCALE_LOG2)) |
35 #define IS_32_BIT (sizeof(void *) == 4) | 35 #define WORD_SIZE (sizeof(uint32_t)) |
| 36 #define IS_32_BIT (sizeof(void *) == WORD_SIZE) |
36 | 37 |
37 #define SHADOW_OFFSET(p) ((uintptr_t)(p) % SHADOW_SCALE) | 38 #define SHADOW_OFFSET(p) ((uintptr_t)(p) % SHADOW_SCALE) |
38 #define IS_SHADOW_ALIGNED(p) (SHADOW_OFFSET(p) == 0) | 39 #define IS_SHADOW_ALIGNED(p) (SHADOW_OFFSET(p) == 0) |
39 | 40 |
40 #define MEM2SHADOW(p) (((uintptr_t)(p) >> SHADOW_SCALE_LOG2) + shadow_offset) | 41 #define MEM2SHADOW(p) (((uintptr_t)(p) >> SHADOW_SCALE_LOG2) + shadow_offset) |
41 #define SHADOW2MEM(p) \ | 42 #define SHADOW2MEM(p) \ |
42 ((uintptr_t)((char *)(p)-shadow_offset) << SHADOW_SCALE_LOG2) | 43 ((uintptr_t)((char *)(p)-shadow_offset) << SHADOW_SCALE_LOG2) |
43 | 44 |
44 #define POISON_VAL (-1) | 45 #define POISON_VAL (-1) |
45 | 46 |
46 static char *shadow_offset = NULL; | 47 static char *shadow_offset = NULL; |
47 | 48 |
| 49 static void __asan_error(char *, int); |
| 50 static void __asan_check(char *, int, bool); |
| 51 |
48 void __asan_init(int, void **, int *); | 52 void __asan_init(int, void **, int *); |
49 void __asan_check(char *, int); | 53 void __asan_check_load(char *, int); |
| 54 void __asan_check_store(char *, int); |
50 void *__asan_malloc(size_t); | 55 void *__asan_malloc(size_t); |
51 void __asan_free(char *); | 56 void __asan_free(char *); |
52 void __asan_poison(char *, int); | 57 void __asan_poison(char *, int); |
53 void __asan_unpoison(char *, int); | 58 void __asan_unpoison(char *, int); |
54 | 59 |
| 60 static void __asan_error(char *ptr, int size) { |
| 61 fprintf(stderr, "Illegal access of %d bytes at %p\n", size, ptr); |
| 62 abort(); |
| 63 } |
| 64 |
| 65 // check only the first byte of each word unless strict |
| 66 static void __asan_check(char *ptr, int size, bool strict) { |
| 67 assert(strict || (uintptr_t)ptr % WORD_SIZE == 0); |
| 68 printf("%s check %d bytes at %p\n", (strict) ? "strict" : "loose", size, ptr); |
| 69 char *end = ptr + size; |
| 70 int step = (strict) ? 1 : WORD_SIZE; |
| 71 for (char *cur = ptr; cur < end; cur += step) { |
| 72 char shadow = *(char *)MEM2SHADOW(cur); |
| 73 printf("checking %p against %p with shadow %d\n", cur, MEM2SHADOW(cur), |
| 74 shadow); |
| 75 if (shadow != 0 && (shadow < 0 || SHADOW_OFFSET(cur) >= shadow)) { |
| 76 __asan_error(ptr, size); |
| 77 } |
| 78 } |
| 79 } |
| 80 |
| 81 void __asan_check_load(char *ptr, int size) { |
| 82 // aligned single word accesses may be widened single byte accesses, but for |
| 83 // all else use strict check |
| 84 bool strict = !((uintptr_t)ptr % WORD_SIZE == 0 && size == WORD_SIZE); |
| 85 __asan_check(ptr, size, strict); |
| 86 } |
| 87 |
| 88 void __asan_check_store(char *ptr, int size) { |
| 89 // stores may never be partially out of bounds so use strict check |
| 90 bool strict = true; |
| 91 __asan_check(ptr, size, strict); |
| 92 } |
| 93 |
55 void __asan_init(int n_rzs, void **rzs, int *rz_sizes) { | 94 void __asan_init(int n_rzs, void **rzs, int *rz_sizes) { |
56 // ensure the redzones are large enough to hold metadata | 95 // ensure the redzones are large enough to hold metadata |
57 assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t)); | 96 assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t)); |
58 assert(shadow_offset == NULL); | 97 assert(shadow_offset == NULL); |
59 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64; | 98 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64; |
60 int prot = PROT_READ | PROT_WRITE; | 99 int prot = PROT_READ | PROT_WRITE; |
61 int flags = MAP_PRIVATE | MAP_ANONYMOUS; | 100 int flags = MAP_PRIVATE | MAP_ANONYMOUS; |
62 int fd = -1; | 101 int fd = -1; |
63 off_t offset = 0; | 102 off_t offset = 0; |
64 shadow_offset = mmap((void *)length, length, prot, flags, fd, offset); | 103 shadow_offset = mmap((void *)length, length, prot, flags, fd, offset); |
65 if (shadow_offset == NULL) | 104 if (shadow_offset == NULL) |
66 fprintf(stderr, "unable to allocate shadow memory\n"); | 105 fprintf(stderr, "unable to allocate shadow memory\n"); |
67 else | 106 else |
68 printf("set up shadow memory at %p\n", shadow_offset); | 107 printf("set up shadow memory at %p\n", shadow_offset); |
69 if (mprotect(MEM2SHADOW(shadow_offset), length >> SHADOW_SCALE_LOG2, | 108 if (mprotect(MEM2SHADOW(shadow_offset), length >> SHADOW_SCALE_LOG2, |
70 PROT_NONE)) | 109 PROT_NONE)) |
71 fprintf(stderr, "could not protect bad region\n"); | 110 fprintf(stderr, "could not protect bad region\n"); |
72 else | 111 else |
73 printf("protected bad region\n"); | 112 printf("protected bad region\n"); |
74 | 113 |
75 // poison global redzones | 114 // poison global redzones |
76 printf("poisioning %d global redzones\n", n_rzs); | 115 printf("poisioning %d global redzones\n", n_rzs); |
77 for (int i = 0; i < n_rzs; i++) { | 116 for (int i = 0; i < n_rzs; i++) { |
78 printf("(%d) poisoning redzone of size %d at %p\n", i, rz_sizes[i], rzs[i]); | 117 printf("(%d) poisoning redzone of size %d at %p\n", i, rz_sizes[i], rzs[i]); |
79 __asan_poison(rzs[i], rz_sizes[i]); | 118 __asan_poison(rzs[i], rz_sizes[i]); |
80 } | 119 } |
81 } | 120 } |
82 | 121 |
83 void __asan_check(char *ptr, int size) { | |
84 printf("check %d bytes at %p\n", size, ptr); | |
85 char *end = ptr + size; | |
86 for (; ptr < end; ++ptr) { | |
87 char shadow = *(char *)MEM2SHADOW(ptr); | |
88 printf("checking %p with shadow %d\n", ptr, shadow); | |
89 if (shadow != 0 && (shadow < 0 || SHADOW_OFFSET(ptr) > shadow)) { | |
90 fprintf(stderr, "Illegal access of %d bytes at %p\n", size, ptr); | |
91 abort(); | |
92 } | |
93 } | |
94 } | |
95 | |
96 void *__asan_malloc(size_t size) { | 122 void *__asan_malloc(size_t size) { |
97 printf("malloc() called with size %d\n", size); | 123 printf("malloc() called with size %d\n", size); |
98 size_t padding = | 124 size_t padding = |
99 (IS_SHADOW_ALIGNED(size)) ? 0 : SHADOW_SCALE - SHADOW_OFFSET(size); | 125 (IS_SHADOW_ALIGNED(size)) ? 0 : SHADOW_SCALE - SHADOW_OFFSET(size); |
100 size_t rz_left_size = RZ_SIZE; | 126 size_t rz_left_size = RZ_SIZE; |
101 size_t rz_right_size = RZ_SIZE + padding; | 127 size_t rz_right_size = RZ_SIZE + padding; |
102 void *rz_left; | 128 void *rz_left; |
103 int err = posix_memalign(&rz_left, SHADOW_SCALE, | 129 int err = posix_memalign(&rz_left, SHADOW_SCALE, |
104 rz_left_size + size + rz_right_size); | 130 rz_left_size + size + rz_right_size); |
105 if (err != 0) { | 131 if (err != 0) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 assert(size < 2 * RZ_SIZE); | 175 assert(size < 2 * RZ_SIZE); |
150 printf("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), | 176 printf("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), |
151 MEM2SHADOW(end)); | 177 MEM2SHADOW(end)); |
152 *(char *)MEM2SHADOW(ptr) = 0; | 178 *(char *)MEM2SHADOW(ptr) = 0; |
153 ptr += SHADOW_OFFSET(size); | 179 ptr += SHADOW_OFFSET(size); |
154 assert(IS_SHADOW_ALIGNED(ptr)); | 180 assert(IS_SHADOW_ALIGNED(ptr)); |
155 for (; ptr != end; ptr += SHADOW_SCALE) { | 181 for (; ptr != end; ptr += SHADOW_SCALE) { |
156 *(char *)MEM2SHADOW(ptr) = 0; | 182 *(char *)MEM2SHADOW(ptr) = 0; |
157 } | 183 } |
158 } | 184 } |
OLD | NEW |