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 |
11 /// \brief Provides the AddressSanitizer runtime. | 11 /// \brief Provides the AddressSanitizer runtime. |
12 /// | 12 /// |
13 /// Exposes functions for initializing the shadow memory region and managing it | 13 /// Exposes functions for initializing the shadow memory region and managing it |
14 /// on loads, stores, and allocations. | 14 /// on loads, stores, and allocations. |
15 /// | 15 /// |
16 //===----------------------------------------------------------------------===// | 16 //===----------------------------------------------------------------------===// |
17 | 17 |
18 #include <assert.h> | 18 #include <assert.h> |
| 19 #include <errno.h> |
| 20 #include <limits.h> |
| 21 #include <stdbool.h> |
19 #include <stddef.h> | 22 #include <stddef.h> |
| 23 #include <stdint.h> |
20 #include <stdio.h> | 24 #include <stdio.h> |
21 #include <stdlib.h> | 25 #include <stdlib.h> |
| 26 #include <sys/mman.h> |
22 | 27 |
23 static __thread int behind_malloc = 0; | 28 #define RZ_SIZE (32) |
| 29 #define SHADOW_SCALE_LOG2 (3) |
| 30 #define SHADOW_SCALE ((size_t)1 << SHADOW_SCALE_LOG2) |
24 | 31 |
25 // TODO(tlively): Define and implement this library | 32 // Assuming 48 bit address space on 64 bit systems |
| 33 #define SHADOW_LENGTH_64 (1u << (48 - SHADOW_SCALE_LOG2)) |
| 34 #define SHADOW_LENGTH_32 (1u << (32 - SHADOW_SCALE_LOG2)) |
| 35 #define IS_32_BIT (sizeof(void *) == 4) |
| 36 |
| 37 #define SHADOW_OFFSET(p) ((uintptr_t)(p) % SHADOW_SCALE) |
| 38 #define IS_SHADOW_ALIGNED(p) (SHADOW_OFFSET(p) == 0) |
| 39 |
| 40 #define MEM2SHADOW(p) (((uintptr_t)(p) >> SHADOW_SCALE_LOG2) + shadow_offset) |
| 41 #define SHADOW2MEM(p) \ |
| 42 ((uintptr_t)((char *)(p)-shadow_offset) << SHADOW_SCALE_LOG2) |
| 43 |
| 44 #define POISON_VAL (-1) |
| 45 |
| 46 static char *shadow_offset = NULL; |
| 47 |
| 48 void __asan_init(void); |
| 49 void __asan_check(char *, int); |
| 50 void *__asan_malloc(size_t); |
| 51 void __asan_free(char *); |
| 52 void __asan_poison(char *, int); |
| 53 void __asan_unpoison(char *, int); |
| 54 |
26 void __asan_init(void) { | 55 void __asan_init(void) { |
27 if (behind_malloc == 0) | 56 // ensure the redzones are large enough to hold metadata |
28 printf("set up shadow memory here\n"); | 57 assert(RZ_SIZE >= sizeof(void *) && RZ_SIZE >= sizeof(size_t)); |
| 58 assert(shadow_offset == NULL); |
| 59 size_t length = (IS_32_BIT) ? SHADOW_LENGTH_32 : SHADOW_LENGTH_64; |
| 60 int prot = PROT_READ | PROT_WRITE; |
| 61 int flags = MAP_PRIVATE | MAP_ANONYMOUS; |
| 62 int fd = -1; |
| 63 off_t offset = 0; |
| 64 shadow_offset = mmap((void *)length, length, prot, flags, fd, offset); |
| 65 if (shadow_offset == NULL) |
| 66 fprintf(stderr, "unable to allocate shadow memory\n"); |
| 67 else |
| 68 printf("set up shadow memory at %p\n", shadow_offset); |
| 69 if (mprotect(MEM2SHADOW(shadow_offset), length >> SHADOW_SCALE_LOG2, |
| 70 PROT_NONE)) |
| 71 fprintf(stderr, "could not protect bad region\n"); |
| 72 else |
| 73 printf("protected bad region\n"); |
29 } | 74 } |
30 | 75 |
31 void __asan_check(void *addr, int size) { | 76 void __asan_check(char *ptr, int size) { |
32 if (behind_malloc == 0) | 77 printf("check %d bytes at %p\n", size, ptr); |
33 printf("check %d bytes at %p\n", size, addr); | 78 char *end = ptr + size; |
| 79 for (; ptr < end; ++ptr) { |
| 80 char shadow = *(char *)MEM2SHADOW(ptr); |
| 81 printf("checking %p with shadow %d\n", ptr, shadow); |
| 82 assert(shadow == 0 || (shadow > 0 && SHADOW_OFFSET(ptr) <= shadow)); |
| 83 } |
34 } | 84 } |
35 | 85 |
36 void *__asan_malloc(size_t size) { | 86 void *__asan_malloc(size_t size) { |
37 if (behind_malloc == 0) | 87 printf("malloc() called with size %d\n", size); |
38 printf("malloc() called with size %d\n", size); | 88 size_t padding = |
39 ++behind_malloc; | 89 (IS_SHADOW_ALIGNED(size)) ? 0 : SHADOW_SCALE - SHADOW_OFFSET(size); |
40 void *ret = malloc(size); | 90 size_t rz_left_size = RZ_SIZE; |
41 --behind_malloc; | 91 size_t rz_right_size = RZ_SIZE + padding; |
42 assert(behind_malloc >= 0); | 92 void *rz_left; |
| 93 int err = posix_memalign(&rz_left, SHADOW_SCALE, |
| 94 rz_left_size + size + rz_right_size); |
| 95 if (err != 0) { |
| 96 assert(err == ENOMEM); |
| 97 return NULL; |
| 98 } |
| 99 void *ret = rz_left + rz_left_size; |
| 100 void *rz_right = ret + size; |
| 101 __asan_poison(rz_left, rz_left_size); |
| 102 __asan_poison(rz_right, rz_right_size); |
| 103 // record size and location data so we can find it again |
| 104 *(void **)rz_left = rz_right; |
| 105 *(size_t *)rz_right = rz_right_size; |
| 106 assert((uintptr_t)ret % 8 == 0); |
43 return ret; | 107 return ret; |
44 } | 108 } |
45 | 109 |
46 void __asan_free(void *ptr) { | 110 void __asan_free(char *ptr) { |
47 if (behind_malloc == 0) | 111 printf("free() called on %p\n", ptr); |
48 printf("free() called on %p\n", ptr); | 112 void *rz_left = ptr - RZ_SIZE; |
49 ++behind_malloc; | 113 void *rz_right = *(void **)rz_left; |
50 free(ptr); | 114 size_t rz_right_size = *(size_t *)rz_right; |
51 --behind_malloc; | 115 __asan_unpoison(rz_left, RZ_SIZE); |
52 assert(behind_malloc >= 0); | 116 __asan_unpoison(rz_right, rz_right_size); |
| 117 free(rz_left); |
53 } | 118 } |
54 | 119 |
55 void __asan_alloca(void *ptr, int size) { | 120 void __asan_poison(char *ptr, int size) { |
56 if (behind_malloc == 0) | 121 char *end = ptr + size; |
57 printf("alloca of %d bytes at %p\n", size, ptr); | 122 assert(IS_SHADOW_ALIGNED(end)); |
| 123 // redzones should be no greater than RZ_SIZE + RZ_SIZE-1 for alignment |
| 124 assert(size < 2 * RZ_SIZE); |
| 125 printf("poison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), |
| 126 MEM2SHADOW(end)); |
| 127 size_t offset = SHADOW_OFFSET(ptr); |
| 128 *(char *)MEM2SHADOW(ptr) = (offset == 0) ? POISON_VAL : offset; |
| 129 ptr += SHADOW_OFFSET(size); |
| 130 assert(IS_SHADOW_ALIGNED(ptr)); |
| 131 for (; ptr != end; ptr += SHADOW_SCALE) { |
| 132 *(char *)MEM2SHADOW(ptr) = POISON_VAL; |
| 133 } |
58 } | 134 } |
59 | 135 |
60 void __asan_unalloca(void *ptr, int size) { | 136 void __asan_unpoison(char *ptr, int size) { |
61 if (behind_malloc == 0) | 137 char *end = ptr + size; |
62 printf("unalloca of %d bytes as %p\n", size, ptr); | 138 assert(IS_SHADOW_ALIGNED(end)); |
| 139 assert(size < 2 * RZ_SIZE); |
| 140 printf("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), |
| 141 MEM2SHADOW(end)); |
| 142 *(char *)MEM2SHADOW(ptr) = 0; |
| 143 ptr += SHADOW_OFFSET(size); |
| 144 assert(IS_SHADOW_ALIGNED(ptr)); |
| 145 for (; ptr != end; ptr += SHADOW_SCALE) { |
| 146 *(char *)MEM2SHADOW(ptr) = 0; |
| 147 } |
63 } | 148 } |
OLD | NEW |