| 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 |