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 10 matching lines...) Expand all Loading... |
21 #include <stdbool.h> | 21 #include <stdbool.h> |
22 #include <stddef.h> | 22 #include <stddef.h> |
23 #include <stdint.h> | 23 #include <stdint.h> |
24 #include <stdio.h> | 24 #include <stdio.h> |
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 #define DEBUG (0) |
31 | 32 |
32 // Assuming 48 bit address space on 64 bit systems | 33 // Assuming 48 bit address space on 64 bit systems |
33 #define SHADOW_LENGTH_64 (1u << (48 - SHADOW_SCALE_LOG2)) | 34 #define SHADOW_LENGTH_64 (1u << (48 - SHADOW_SCALE_LOG2)) |
34 #define SHADOW_LENGTH_32 (1u << (32 - SHADOW_SCALE_LOG2)) | 35 #define SHADOW_LENGTH_32 (1u << (32 - SHADOW_SCALE_LOG2)) |
35 #define WORD_SIZE (sizeof(uint32_t)) | 36 #define WORD_SIZE (sizeof(uint32_t)) |
36 #define IS_32_BIT (sizeof(void *) == WORD_SIZE) | 37 #define IS_32_BIT (sizeof(void *) == WORD_SIZE) |
37 | 38 |
38 #define SHADOW_OFFSET(p) ((uintptr_t)(p) % SHADOW_SCALE) | 39 #define SHADOW_OFFSET(p) ((uintptr_t)(p) % SHADOW_SCALE) |
39 #define IS_SHADOW_ALIGNED(p) (SHADOW_OFFSET(p) == 0) | 40 #define IS_SHADOW_ALIGNED(p) (SHADOW_OFFSET(p) == 0) |
40 | 41 |
41 #define MEM2SHADOW(p) (((uintptr_t)(p) >> SHADOW_SCALE_LOG2) + shadow_offset) | 42 #define MEM2SHADOW(p) (((uintptr_t)(p) >> SHADOW_SCALE_LOG2) + shadow_offset) |
42 #define SHADOW2MEM(p) \ | 43 #define SHADOW2MEM(p) \ |
43 ((uintptr_t)((char *)(p)-shadow_offset) << SHADOW_SCALE_LOG2) | 44 ((uintptr_t)((char *)(p)-shadow_offset) << SHADOW_SCALE_LOG2) |
44 | 45 |
45 #define POISON_VAL (-1) | 46 #define POISON_VAL (-1) |
46 | 47 |
| 48 #if DEBUG |
| 49 #define DUMP(args...) \ |
| 50 do { \ |
| 51 printf(args); \ |
| 52 } while (false); |
| 53 #else // !DEBUG |
| 54 #define DUMP(args...) |
| 55 #endif // DEBUG |
| 56 |
47 static char *shadow_offset = NULL; | 57 static char *shadow_offset = NULL; |
48 | 58 |
49 static void __asan_error(char *, int); | 59 static void __asan_error(char *, int); |
50 static void __asan_check(char *, int, bool); | 60 static void __asan_check(char *, int, bool); |
51 | 61 |
52 void __asan_init(int, void **, int *); | 62 void __asan_init(int, void **, int *); |
53 void __asan_check_load(char *, int); | 63 void __asan_check_load(char *, int); |
54 void __asan_check_store(char *, int); | 64 void __asan_check_store(char *, int); |
55 void *__asan_malloc(size_t); | 65 void *__asan_malloc(size_t); |
56 void __asan_free(char *); | 66 void __asan_free(char *); |
57 void __asan_poison(char *, int); | 67 void __asan_poison(char *, int); |
58 void __asan_unpoison(char *, int); | 68 void __asan_unpoison(char *, int); |
59 | 69 |
60 static void __asan_error(char *ptr, int size) { | 70 static void __asan_error(char *ptr, int size) { |
61 fprintf(stderr, "Illegal access of %d bytes at %p\n", size, ptr); | 71 fprintf(stderr, "Illegal access of %d bytes at %p\n", size, ptr); |
62 abort(); | 72 abort(); |
63 } | 73 } |
64 | 74 |
65 // check only the first byte of each word unless strict | 75 // check only the first byte of each word unless strict |
66 static void __asan_check(char *ptr, int size, bool strict) { | 76 static void __asan_check(char *ptr, int size, bool strict) { |
67 assert(strict || (uintptr_t)ptr % WORD_SIZE == 0); | 77 assert(strict || (uintptr_t)ptr % WORD_SIZE == 0); |
68 printf("%s check %d bytes at %p\n", (strict) ? "strict" : "loose", size, ptr); | 78 DUMP("%s check %d bytes at %p\n", (strict) ? "strict" : "loose", size, ptr); |
69 char *end = ptr + size; | 79 char *end = ptr + size; |
70 int step = (strict) ? 1 : WORD_SIZE; | 80 int step = (strict) ? 1 : WORD_SIZE; |
71 for (char *cur = ptr; cur < end; cur += step) { | 81 for (char *cur = ptr; cur < end; cur += step) { |
72 char shadow = *(char *)MEM2SHADOW(cur); | 82 char shadow = *(char *)MEM2SHADOW(cur); |
73 printf("checking %p against %p with shadow %d\n", cur, MEM2SHADOW(cur), | 83 DUMP("checking %p against %p with shadow %d\n", cur, MEM2SHADOW(cur), |
74 shadow); | 84 shadow); |
75 if (shadow != 0 && (shadow < 0 || SHADOW_OFFSET(cur) >= shadow)) { | 85 if (shadow != 0 && (shadow < 0 || SHADOW_OFFSET(cur) >= shadow)) { |
76 __asan_error(ptr, size); | 86 __asan_error(ptr, size); |
77 } | 87 } |
78 } | 88 } |
79 } | 89 } |
80 | 90 |
81 void __asan_check_load(char *ptr, int size) { | 91 void __asan_check_load(char *ptr, int size) { |
82 // aligned single word accesses may be widened single byte accesses, but for | 92 // aligned single word accesses may be widened single byte accesses, but for |
83 // all else use strict check | 93 // all else use strict check |
84 bool strict = !((uintptr_t)ptr % WORD_SIZE == 0 && size == WORD_SIZE); | 94 bool strict = !((uintptr_t)ptr % WORD_SIZE == 0 && size == WORD_SIZE); |
(...skipping 12 matching lines...) Expand all Loading... |
97 assert(shadow_offset == NULL); | 107 assert(shadow_offset == NULL); |
98 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64; | 108 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64; |
99 int prot = PROT_READ | PROT_WRITE; | 109 int prot = PROT_READ | PROT_WRITE; |
100 int flags = MAP_PRIVATE | MAP_ANONYMOUS; | 110 int flags = MAP_PRIVATE | MAP_ANONYMOUS; |
101 int fd = -1; | 111 int fd = -1; |
102 off_t offset = 0; | 112 off_t offset = 0; |
103 shadow_offset = mmap((void *)length, length, prot, flags, fd, offset); | 113 shadow_offset = mmap((void *)length, length, prot, flags, fd, offset); |
104 if (shadow_offset == NULL) | 114 if (shadow_offset == NULL) |
105 fprintf(stderr, "unable to allocate shadow memory\n"); | 115 fprintf(stderr, "unable to allocate shadow memory\n"); |
106 else | 116 else |
107 printf("set up shadow memory at %p\n", shadow_offset); | 117 DUMP("set up shadow memory at %p\n", shadow_offset); |
108 if (mprotect(MEM2SHADOW(shadow_offset), length >> SHADOW_SCALE_LOG2, | 118 if (mprotect(MEM2SHADOW(shadow_offset), length >> SHADOW_SCALE_LOG2, |
109 PROT_NONE)) | 119 PROT_NONE)) |
110 fprintf(stderr, "could not protect bad region\n"); | 120 fprintf(stderr, "could not protect bad region\n"); |
111 else | 121 else |
112 printf("protected bad region\n"); | 122 DUMP("protected bad region\n"); |
113 | 123 |
114 // poison global redzones | 124 // poison global redzones |
115 printf("poisioning %d global redzones\n", n_rzs); | 125 DUMP("poisioning %d global redzones\n", n_rzs); |
116 for (int i = 0; i < n_rzs; i++) { | 126 for (int i = 0; i < n_rzs; i++) { |
117 printf("(%d) poisoning redzone of size %d at %p\n", i, rz_sizes[i], rzs[i]); | 127 DUMP("(%d) poisoning redzone of size %d at %p\n", i, rz_sizes[i], rzs[i]); |
118 __asan_poison(rzs[i], rz_sizes[i]); | 128 __asan_poison(rzs[i], rz_sizes[i]); |
119 } | 129 } |
120 } | 130 } |
121 | 131 |
122 void *__asan_malloc(size_t size) { | 132 void *__asan_malloc(size_t size) { |
123 printf("malloc() called with size %d\n", size); | 133 DUMP("malloc() called with size %d\n", size); |
124 size_t padding = | 134 size_t padding = |
125 (IS_SHADOW_ALIGNED(size)) ? 0 : SHADOW_SCALE - SHADOW_OFFSET(size); | 135 (IS_SHADOW_ALIGNED(size)) ? 0 : SHADOW_SCALE - SHADOW_OFFSET(size); |
126 size_t rz_left_size = RZ_SIZE; | 136 size_t rz_left_size = RZ_SIZE; |
127 size_t rz_right_size = RZ_SIZE + padding; | 137 size_t rz_right_size = RZ_SIZE + padding; |
128 void *rz_left; | 138 void *rz_left; |
129 int err = posix_memalign(&rz_left, SHADOW_SCALE, | 139 int err = posix_memalign(&rz_left, SHADOW_SCALE, |
130 rz_left_size + size + rz_right_size); | 140 rz_left_size + size + rz_right_size); |
131 if (err != 0) { | 141 if (err != 0) { |
132 assert(err == ENOMEM); | 142 assert(err == ENOMEM); |
133 return NULL; | 143 return NULL; |
134 } | 144 } |
135 void *ret = rz_left + rz_left_size; | 145 void *ret = rz_left + rz_left_size; |
136 void *rz_right = ret + size; | 146 void *rz_right = ret + size; |
137 __asan_poison(rz_left, rz_left_size); | 147 __asan_poison(rz_left, rz_left_size); |
138 __asan_poison(rz_right, rz_right_size); | 148 __asan_poison(rz_right, rz_right_size); |
139 // record size and location data so we can find it again | 149 // record size and location data so we can find it again |
140 *(void **)rz_left = rz_right; | 150 *(void **)rz_left = rz_right; |
141 *(size_t *)rz_right = rz_right_size; | 151 *(size_t *)rz_right = rz_right_size; |
142 assert((uintptr_t)ret % 8 == 0); | 152 assert((uintptr_t)ret % 8 == 0); |
143 return ret; | 153 return ret; |
144 } | 154 } |
145 | 155 |
146 void __asan_free(char *ptr) { | 156 void __asan_free(char *ptr) { |
147 printf("free() called on %p\n", ptr); | 157 DUMP("free() called on %p\n", ptr); |
148 void *rz_left = ptr - RZ_SIZE; | 158 void *rz_left = ptr - RZ_SIZE; |
149 void *rz_right = *(void **)rz_left; | 159 void *rz_right = *(void **)rz_left; |
150 size_t rz_right_size = *(size_t *)rz_right; | 160 size_t rz_right_size = *(size_t *)rz_right; |
151 __asan_unpoison(rz_left, RZ_SIZE); | 161 __asan_unpoison(rz_left, RZ_SIZE); |
152 __asan_unpoison(rz_right, rz_right_size); | 162 __asan_unpoison(rz_right, rz_right_size); |
153 free(rz_left); | 163 free(rz_left); |
154 } | 164 } |
155 | 165 |
156 void __asan_poison(char *ptr, int size) { | 166 void __asan_poison(char *ptr, int size) { |
157 char *end = ptr + size; | 167 char *end = ptr + size; |
158 assert(IS_SHADOW_ALIGNED(end)); | 168 assert(IS_SHADOW_ALIGNED(end)); |
159 // redzones should be no greater than RZ_SIZE + RZ_SIZE-1 for alignment | 169 // redzones should be no greater than RZ_SIZE + RZ_SIZE-1 for alignment |
160 assert(size < 2 * RZ_SIZE); | 170 assert(size < 2 * RZ_SIZE); |
161 printf("poison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), | 171 DUMP("poison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), |
162 MEM2SHADOW(end)); | 172 MEM2SHADOW(end)); |
163 size_t offset = SHADOW_OFFSET(ptr); | 173 size_t offset = SHADOW_OFFSET(ptr); |
164 *(char *)MEM2SHADOW(ptr) = (offset == 0) ? POISON_VAL : offset; | 174 *(char *)MEM2SHADOW(ptr) = (offset == 0) ? POISON_VAL : offset; |
165 ptr += SHADOW_OFFSET(size); | 175 ptr += SHADOW_OFFSET(size); |
166 assert(IS_SHADOW_ALIGNED(ptr)); | 176 assert(IS_SHADOW_ALIGNED(ptr)); |
167 for (; ptr != end; ptr += SHADOW_SCALE) { | 177 for (; ptr != end; ptr += SHADOW_SCALE) { |
168 *(char *)MEM2SHADOW(ptr) = POISON_VAL; | 178 *(char *)MEM2SHADOW(ptr) = POISON_VAL; |
169 } | 179 } |
170 } | 180 } |
171 | 181 |
172 void __asan_unpoison(char *ptr, int size) { | 182 void __asan_unpoison(char *ptr, int size) { |
173 char *end = ptr + size; | 183 char *end = ptr + size; |
174 assert(IS_SHADOW_ALIGNED(end)); | 184 assert(IS_SHADOW_ALIGNED(end)); |
175 assert(size < 2 * RZ_SIZE); | 185 assert(size < 2 * RZ_SIZE); |
176 printf("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), | 186 DUMP("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), |
177 MEM2SHADOW(end)); | 187 MEM2SHADOW(end)); |
178 *(char *)MEM2SHADOW(ptr) = 0; | 188 *(char *)MEM2SHADOW(ptr) = 0; |
179 ptr += SHADOW_OFFSET(size); | 189 ptr += SHADOW_OFFSET(size); |
180 assert(IS_SHADOW_ALIGNED(ptr)); | 190 assert(IS_SHADOW_ALIGNED(ptr)); |
181 for (; ptr != end; ptr += SHADOW_SCALE) { | 191 for (; ptr != end; ptr += SHADOW_SCALE) { |
182 *(char *)MEM2SHADOW(ptr) = 0; | 192 *(char *)MEM2SHADOW(ptr) = 0; |
183 } | 193 } |
184 } | 194 } |
OLD | NEW |