| 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 do { \ | 83 do { \ |
| 84 printf(args); \ | 84 printf(args); \ |
| 85 } while (false); | 85 } while (false); |
| 86 #else // !DEBUG | 86 #else // !DEBUG |
| 87 #define DUMP(args...) | 87 #define DUMP(args...) |
| 88 #endif // DEBUG | 88 #endif // DEBUG |
| 89 | 89 |
| 90 static char *shadow_offset = NULL; | 90 static char *shadow_offset = NULL; |
| 91 | 91 |
| 92 static bool __asan_check(char *, int); | 92 static bool __asan_check(char *, int); |
| 93 static void __asan_error(char *, int, int); | 93 static void __asan_error(char *, int, int, void *); |
| 94 static void __asan_get_redzones(char *, char **, char **); | 94 static void __asan_get_redzones(char *, char **, char **); |
| 95 | 95 |
| 96 void __asan_init(int, void **, int *); | 96 void __asan_init(int, void **, int *); |
| 97 void __asan_check_load(char *, int); | 97 void __asan_check_load(char *, int); |
| 98 void __asan_check_store(char *, int); | 98 void __asan_check_store(char *, int); |
| 99 void *__asan_malloc(size_t); | 99 void *__asan_malloc(size_t); |
| 100 void *__asan_calloc(size_t, size_t); | 100 void *__asan_calloc(size_t, size_t); |
| 101 void *__asan_realloc(char *, size_t); | 101 void *__asan_realloc(char *, size_t); |
| 102 void __asan_free(char *); | 102 void __asan_free(char *); |
| 103 void __asan_poison(char *, int, char); | 103 void __asan_poison(char *, int, char); |
| 104 void __asan_unpoison(char *, int); | 104 void __asan_unpoison(char *, int); |
| 105 | 105 |
| 106 struct quarantine_entry { | 106 struct quarantine_entry { |
| 107 struct quarantine_entry *next; | 107 struct quarantine_entry *next; |
| 108 size_t size; | 108 size_t size; |
| 109 }; | 109 }; |
| 110 | 110 |
| 111 mutex_t quarantine_lock = MUTEX_INITIALIZER; | 111 mutex_t quarantine_lock = MUTEX_INITIALIZER; |
| 112 uint64_t quarantine_size = 0; | 112 uint64_t quarantine_size = 0; |
| 113 struct quarantine_entry *quarantine_head = NULL; | 113 struct quarantine_entry *quarantine_head = NULL; |
| 114 struct quarantine_entry *quarantine_tail = NULL; | 114 struct quarantine_entry *quarantine_tail = NULL; |
| 115 | 115 |
| 116 static void __asan_error(char *ptr, int size, int access) { | 116 static void __asan_error(char *ptr, int size, int access, void *ret_addr) { |
| 117 char *shadow_addr = MEM2SHADOW(ptr); | 117 char *shadow_addr = MEM2SHADOW(ptr); |
| 118 char shadow_val = *shadow_addr; | 118 char shadow_val = *shadow_addr; |
| 119 if (shadow_val > 0) | 119 if (shadow_val > 0) |
| 120 shadow_val = *(shadow_addr + 1); | 120 shadow_val = *(shadow_addr + 1); |
| 121 assert(access == ACCESS_LOAD || access == ACCESS_STORE); | 121 assert(access == ACCESS_LOAD || access == ACCESS_STORE); |
| 122 const char *access_name = access_names[access]; | 122 const char *access_name = access_names[access]; |
| 123 assert(shadow_val == STACK_POISON_VAL || shadow_val == HEAP_POISON_VAL || | 123 assert(shadow_val == STACK_POISON_VAL || shadow_val == HEAP_POISON_VAL || |
| 124 shadow_val == GLOBAL_POISON_VAL || shadow_val == FREED_POISON_VAL); | 124 shadow_val == GLOBAL_POISON_VAL || shadow_val == FREED_POISON_VAL); |
| 125 const char *memtype = memtype_names[MEMTYPE_INDEX(shadow_val)]; | 125 const char *memtype = memtype_names[MEMTYPE_INDEX(shadow_val)]; |
| 126 fprintf(stderr, "Illegal %d byte %s %s object at %p\n", size, access_name, | 126 fprintf(stderr, "%p: Illegal %d byte %s %s object at %p\n", ret_addr, size, |
| 127 memtype, ptr); | 127 access_name, memtype, ptr); |
| 128 fprintf(stderr, "(address of __asan_error symbol is %p)\n", __asan_error); |
| 128 abort(); | 129 abort(); |
| 129 } | 130 } |
| 130 | 131 |
| 131 // check only the first byte of each word unless strict | 132 // check only the first byte of each word unless strict |
| 132 static bool __asan_check(char *ptr, int size) { | 133 static bool __asan_check(char *ptr, int size) { |
| 133 assert(size == 1 || size == 2 || size == 4 || size == 8); | 134 assert(size == 1 || size == 2 || size == 4 || size == 8); |
| 134 char *shadow_addr = (char *)MEM2SHADOW(ptr); | 135 char *shadow_addr = (char *)MEM2SHADOW(ptr); |
| 135 char shadow_val = *shadow_addr; | 136 char shadow_val = *shadow_addr; |
| 136 DUMP("check %d bytes at %p: %p + %d (%d)\n", size, ptr, shadow_addr, | 137 DUMP("check %d bytes at %p: %p + %d (%d)\n", size, ptr, shadow_addr, |
| 137 (uintptr_t)ptr % SHADOW_SCALE, shadow_val); | 138 (uintptr_t)ptr % SHADOW_SCALE, shadow_val); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 149 if (right != NULL) | 150 if (right != NULL) |
| 150 *right = rz_right; | 151 *right = rz_right; |
| 151 } | 152 } |
| 152 | 153 |
| 153 void __asan_check_load(char *ptr, int size) { | 154 void __asan_check_load(char *ptr, int size) { |
| 154 // aligned single word accesses may be widened single byte accesses, but for | 155 // aligned single word accesses may be widened single byte accesses, but for |
| 155 // all else use strict check | 156 // all else use strict check |
| 156 int check_size = | 157 int check_size = |
| 157 (size == WORD_SIZE && (uintptr_t)ptr % WORD_SIZE == 0) ? 1 : size; | 158 (size == WORD_SIZE && (uintptr_t)ptr % WORD_SIZE == 0) ? 1 : size; |
| 158 if (!__asan_check(ptr, check_size)) | 159 if (!__asan_check(ptr, check_size)) |
| 159 __asan_error(ptr, size, ACCESS_LOAD); | 160 __asan_error(ptr, size, ACCESS_LOAD, __builtin_return_address(0)); |
| 160 } | 161 } |
| 161 | 162 |
| 162 void __asan_check_store(char *ptr, int size) { | 163 void __asan_check_store(char *ptr, int size) { |
| 163 // stores may never be partially out of bounds so use strict check | 164 // stores may never be partially out of bounds so use strict check |
| 164 if (!__asan_check(ptr, size)) | 165 if (!__asan_check(ptr, size)) |
| 165 __asan_error(ptr, size, ACCESS_STORE); | 166 __asan_error(ptr, size, ACCESS_STORE, __builtin_return_address(0)); |
| 166 } | 167 } |
| 167 | 168 |
| 168 void __asan_init(int n_rzs, void **rzs, int *rz_sizes) { | 169 void __asan_init(int n_rzs, void **rzs, int *rz_sizes) { |
| 169 // ensure the redzones are large enough to hold metadata | 170 // ensure the redzones are large enough to hold metadata |
| 170 assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t)); | 171 assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t)); |
| 171 assert(shadow_offset == NULL); | 172 assert(shadow_offset == NULL); |
| 172 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64; | 173 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64; |
| 173 int prot = PROT_READ | PROT_WRITE; | 174 int prot = PROT_READ | PROT_WRITE; |
| 174 int flags = MAP_PRIVATE | MAP_ANONYMOUS; | 175 int flags = MAP_PRIVATE | MAP_ANONYMOUS; |
| 175 int fd = -1; | 176 int fd = -1; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 memcpy(new_alloc, ptr, copyable); | 244 memcpy(new_alloc, ptr, copyable); |
| 244 __asan_free(ptr); | 245 __asan_free(ptr); |
| 245 return new_alloc; | 246 return new_alloc; |
| 246 } | 247 } |
| 247 | 248 |
| 248 void __asan_free(char *ptr) { | 249 void __asan_free(char *ptr) { |
| 249 DUMP("free() called on %p\n", ptr); | 250 DUMP("free() called on %p\n", ptr); |
| 250 if (ptr == NULL) | 251 if (ptr == NULL) |
| 251 return; | 252 return; |
| 252 if (*(char *)MEM2SHADOW(ptr) == FREED_POISON_VAL) { | 253 if (*(char *)MEM2SHADOW(ptr) == FREED_POISON_VAL) { |
| 253 fprintf(stderr, "Double free of object at %p\n", ptr); | 254 fprintf(stderr, "%p: Double free of object at %p\n", |
| 255 __builtin_return_address(0), ptr); |
| 256 fprintf(stderr, "(address of __asan_error symbol is %p)\n", __asan_error); |
| 254 abort(); | 257 abort(); |
| 255 } | 258 } |
| 256 char *rz_left, *rz_right; | 259 char *rz_left, *rz_right; |
| 257 __asan_get_redzones(ptr, &rz_left, &rz_right); | 260 __asan_get_redzones(ptr, &rz_left, &rz_right); |
| 258 size_t rz_right_size = *(size_t *)rz_right; | 261 size_t rz_right_size = *(size_t *)rz_right; |
| 259 size_t total_size = rz_right_size + (rz_right - rz_left); | 262 size_t total_size = rz_right_size + (rz_right - rz_left); |
| 260 __asan_poison(rz_left, total_size, FREED_POISON_VAL); | 263 __asan_poison(rz_left, total_size, FREED_POISON_VAL); |
| 261 | 264 |
| 262 // place allocation in quarantine | 265 // place allocation in quarantine |
| 263 struct quarantine_entry *entry = (struct quarantine_entry *)rz_left; | 266 struct quarantine_entry *entry = (struct quarantine_entry *)rz_left; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 void __asan_unpoison(char *ptr, int size) { | 308 void __asan_unpoison(char *ptr, int size) { |
| 306 char *end = ptr + size; | 309 char *end = ptr + size; |
| 307 assert(IS_SHADOW_ALIGNED(end)); | 310 assert(IS_SHADOW_ALIGNED(end)); |
| 308 DUMP("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), | 311 DUMP("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), |
| 309 MEM2SHADOW(end)); | 312 MEM2SHADOW(end)); |
| 310 *(char *)MEM2SHADOW(ptr) = 0; | 313 *(char *)MEM2SHADOW(ptr) = 0; |
| 311 ptr += SHADOW_OFFSET(size); | 314 ptr += SHADOW_OFFSET(size); |
| 312 assert(IS_SHADOW_ALIGNED(ptr)); | 315 assert(IS_SHADOW_ALIGNED(ptr)); |
| 313 memset(MEM2SHADOW(ptr), 0, (end - ptr) >> SHADOW_SCALE_LOG2); | 316 memset(MEM2SHADOW(ptr), 0, (end - ptr) >> SHADOW_SCALE_LOG2); |
| 314 } | 317 } |
| OLD | NEW |