Chromium Code Reviews| 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 <limits.h> | |
| 20 #include <stdbool.h> | |
| 19 #include <stddef.h> | 21 #include <stddef.h> |
| 22 #include <stdint.h> | |
| 20 #include <stdio.h> | 23 #include <stdio.h> |
| 21 #include <stdlib.h> | 24 #include <stdlib.h> |
| 25 #include <sys/mman.h> | |
| 22 | 26 |
| 23 static __thread int behind_malloc = 0; | 27 #define RZ_SIZE (32) |
| 28 #define MEM2SHADOW(p) (((uintptr_t)(p) >> 3) + shadow_offset) | |
|
Karl
2016/06/23 21:55:52
Create a symbolic name for 3 (like kByteLog2). The
tlively
2016/06/24 05:39:21
Done.
| |
| 29 #define SHADOW2MEM(p) ((uintptr_t)((char *)(p)-shadow_offset) << 3) | |
| 24 | 30 |
| 25 // TODO(tlively): Define and implement this library | 31 // greater than zero iff malloc is in the call stack |
| 32 static char *shadow_offset = NULL; | |
| 33 static __thread bool behind_malloc = false; | |
| 34 | |
| 35 void __asan_init(void); | |
| 36 void __asan_check(char *, int); | |
| 37 void *__asan_malloc(size_t); | |
| 38 void __asan_free(char *); | |
| 39 void __asan_poison(char *, int); | |
| 40 void __asan_unpoison(char *, int); | |
| 41 | |
| 26 void __asan_init(void) { | 42 void __asan_init(void) { |
|
Karl
2016/06/23 21:55:51
Since __asan_malloc assumes that
RS_SIZE >= si
tlively
2016/06/24 05:39:21
Done.
| |
| 27 if (behind_malloc == 0) | 43 assert(shadow_offset == NULL); |
| 28 printf("set up shadow memory here\n"); | 44 size_t length = (sizeof(void *) == 4) ? 1 << 29 : 0x0000100000000000; |
|
Karl
2016/06/23 21:55:51
Again, create a symbolic name for 29?
Also, you ma
tlively
2016/06/24 05:39:21
Done.
| |
| 45 int prot = PROT_READ | PROT_WRITE; | |
| 46 int flags = MAP_PRIVATE | MAP_ANONYMOUS; | |
| 47 int fd = -1; | |
| 48 off_t offset = 0; | |
| 49 shadow_offset = mmap((void *)length, length, prot, flags, fd, offset); | |
| 50 if (shadow_offset == NULL) | |
| 51 fprintf(stderr, "Unable to allocate shadow memory\n"); | |
| 52 else | |
| 53 printf("set up shadow memory at %p\n", shadow_offset); | |
| 54 if (mprotect(MEM2SHADOW(shadow_offset), length >> 3, PROT_NONE)) | |
| 55 fprintf(stderr, "could not protect bad region\n"); | |
| 56 else | |
| 57 printf("protected bad region\n"); | |
| 29 } | 58 } |
| 30 | 59 |
| 31 void __asan_check(void *addr, int size) { | 60 void __asan_check(char *ptr, int size) { |
| 32 if (behind_malloc == 0) | 61 if (behind_malloc) |
| 33 printf("check %d bytes at %p\n", size, addr); | 62 return; |
| 63 printf("check %d bytes at %p\n", size, ptr); | |
| 64 char *end = ptr + size; | |
| 65 for (; ptr < end; ++ptr) { | |
| 66 char shadow = *(char *)MEM2SHADOW(ptr); | |
| 67 printf("checking %p with shadow %d\n", ptr, shadow); | |
| 68 assert(shadow == 0 || (shadow >= 0 && (uintptr_t)ptr % 8 <= shadow)); | |
| 69 } | |
| 34 } | 70 } |
| 35 | 71 |
| 36 void *__asan_malloc(size_t size) { | 72 void *__asan_malloc(size_t size) { |
| 37 if (behind_malloc == 0) | 73 if (behind_malloc) |
| 38 printf("malloc() called with size %d\n", size); | 74 return malloc(size); |
| 39 ++behind_malloc; | 75 printf("malloc() called with size %d\n", size); |
| 40 void *ret = malloc(size); | 76 size_t padding = (size % CHAR_BIT == 0) ? 0 : CHAR_BIT - size % CHAR_BIT; |
| 41 --behind_malloc; | 77 size_t rz_left_size = RZ_SIZE; |
| 42 assert(behind_malloc >= 0); | 78 size_t rz_right_size = RZ_SIZE + padding; |
| 79 behind_malloc = true; | |
| 80 char *rz_left = malloc(rz_left_size + size + rz_right_size); | |
| 81 behind_malloc = false; | |
| 82 void *ret = rz_left + rz_left_size; | |
| 83 void *rz_right = ret + size; | |
| 84 __asan_poison(rz_left, rz_left_size); | |
| 85 __asan_poison(rz_right, rz_right_size); | |
| 86 // record size and location data so we can find it again | |
| 87 *(void **)rz_left = rz_right; | |
|
Karl
2016/06/23 21:55:52
Since types like
(void **)
and
(size_t *)
tlively
2016/06/24 05:39:21
What sort of names might be appropriate for these
| |
| 88 *(size_t *)rz_right = rz_right_size; | |
| 89 assert((uintptr_t)ret % 8 == 0); | |
| 43 return ret; | 90 return ret; |
| 44 } | 91 } |
| 45 | 92 |
| 46 void __asan_free(void *ptr) { | 93 void __asan_free(char *ptr) { |
| 47 if (behind_malloc == 0) | 94 if (behind_malloc) { |
| 48 printf("free() called on %p\n", ptr); | 95 free(ptr); |
| 49 ++behind_malloc; | 96 return; |
| 50 free(ptr); | 97 } |
| 51 --behind_malloc; | 98 printf("free() called on %p\n", ptr); |
| 52 assert(behind_malloc >= 0); | 99 void *rz_left = ptr - RZ_SIZE; |
| 100 void *rz_right = *(void **)rz_left; | |
| 101 size_t rz_right_size = *(size_t *)rz_right; | |
| 102 __asan_unpoison(rz_left, RZ_SIZE); | |
| 103 __asan_unpoison(rz_right, rz_right_size); | |
| 104 free(rz_left); | |
| 53 } | 105 } |
| 54 | 106 |
| 55 void __asan_alloca(void *ptr, int size) { | 107 void __asan_poison(char *ptr, int size) { |
| 56 if (behind_malloc == 0) | 108 char *end = ptr + size; |
| 57 printf("alloca of %d bytes at %p\n", size, ptr); | 109 assert((uintptr_t)end % 8 == 0); |
|
Karl
2016/06/23 21:55:52
CHAR_BIT instead of 8?
Also, consider defining a
tlively
2016/06/24 05:39:22
Done.
| |
| 110 assert(size < 64); | |
|
Karl
2016/06/23 21:55:52
Why the magic number 64?
tlively
2016/06/24 05:39:21
Done.
| |
| 111 if (behind_malloc) | |
| 112 return; | |
| 113 printf("poison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), | |
| 114 MEM2SHADOW(end)); | |
| 115 size_t offset = (uintptr_t)ptr % 8; | |
| 116 *(char *)MEM2SHADOW(ptr) = (offset) == 0 ? -1 : offset; | |
| 117 ptr += size % 8; | |
|
Karl
2016/06/23 21:55:52
How about defining a macro for cases of (X % 8) an
tlively
2016/06/24 05:39:22
Done.
| |
| 118 assert((uintptr_t)ptr % 8 == 0); | |
| 119 for (; ptr != end; ptr += 8) { | |
| 120 *(char *)MEM2SHADOW(ptr) = -1; | |
| 121 } | |
| 58 } | 122 } |
| 59 | 123 |
| 60 void __asan_unalloca(void *ptr, int size) { | 124 void __asan_unpoison(char *ptr, int size) { |
| 61 if (behind_malloc == 0) | 125 char *end = ptr + size; |
| 62 printf("unalloca of %d bytes as %p\n", size, ptr); | 126 assert((uintptr_t)end % 8 == 0); |
| 127 assert(size < 64); | |
| 128 if (behind_malloc) | |
| 129 return; | |
| 130 printf("unpoison %d bytes at %p: %p - %p\n", size, ptr, MEM2SHADOW(ptr), | |
| 131 MEM2SHADOW(end)); | |
| 132 *(char *)MEM2SHADOW(ptr) = 0; | |
| 133 ptr += size % 8; | |
| 134 assert((uintptr_t)ptr % 8 == 0); | |
| 135 for (; ptr != end; ptr += 8) { | |
| 136 *(char *)MEM2SHADOW(ptr) = 0; | |
| 137 } | |
| 63 } | 138 } |
|
Karl
2016/06/23 21:55:51
In general, this code looks right. However, it is
tlively
2016/06/24 05:39:21
Done, and with the changes I briefly tested changi
| |
| OLD | NEW |