1 /* AddressSanitizer, a fast memory error detector. 2 Copyright (C) 2011-2021 Free Software Foundation, Inc. 3 Contributed by Kostya Serebryany <kcc@google.com> 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it under 8 the terms of the GNU General Public License as published by the Free 9 Software Foundation; either version 3, or (at your option) any later 10 version. 11 12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #ifndef TREE_ASAN 22 #define TREE_ASAN 23 24 extern void asan_function_start (void); 25 extern void asan_finish_file (void); 26 extern rtx_insn *asan_emit_stack_protection (rtx, rtx, unsigned int, 27 HOST_WIDE_INT *, tree *, int); 28 extern rtx_insn *asan_emit_allocas_unpoison (rtx, rtx, rtx_insn *); 29 extern bool asan_protect_global (tree, bool ignore_decl_rtl_set_p = false); 30 extern void initialize_sanitizer_builtins (void); 31 extern tree asan_dynamic_init_call (bool); 32 extern bool asan_expand_check_ifn (gimple_stmt_iterator *, bool); 33 extern bool asan_expand_mark_ifn (gimple_stmt_iterator *); 34 extern bool asan_expand_poison_ifn (gimple_stmt_iterator *, bool *, 35 hash_map<tree, tree> &); 36 37 extern void hwasan_record_frame_init (); 38 extern void hwasan_record_stack_var (rtx, rtx, poly_int64, poly_int64); 39 extern void hwasan_emit_prologue (); 40 extern rtx_insn *hwasan_emit_untag_frame (rtx, rtx); 41 extern rtx hwasan_get_frame_extent (); 42 extern rtx hwasan_frame_base (); 43 extern void hwasan_maybe_emit_frame_base_init (void); 44 extern bool stack_vars_base_reg_p (rtx); 45 extern uint8_t hwasan_current_frame_tag (); 46 extern void hwasan_increment_frame_tag (); 47 extern rtx hwasan_truncate_to_tag_size (rtx, rtx); 48 extern void hwasan_finish_file (void); 49 extern bool hwasan_sanitize_p (void); 50 extern bool hwasan_sanitize_stack_p (void); 51 extern bool hwasan_sanitize_allocas_p (void); 52 extern bool hwasan_expand_check_ifn (gimple_stmt_iterator *, bool); 53 extern bool hwasan_expand_mark_ifn (gimple_stmt_iterator *); 54 extern bool gate_hwasan (void); 55 56 extern gimple_stmt_iterator create_cond_insert_point 57 (gimple_stmt_iterator *, bool, bool, bool, basic_block *, basic_block *); 58 59 /* Alias set for accessing the shadow memory. */ 60 extern alias_set_type asan_shadow_set; 61 62 /* Hash set of labels that are either used in a goto, or their address 63 has been taken. */ 64 extern hash_set <tree> *asan_used_labels; 65 66 /* Shadow memory is found at 67 (address >> ASAN_SHADOW_SHIFT) + asan_shadow_offset (). */ 68 #define ASAN_SHADOW_SHIFT 3 69 #define ASAN_SHADOW_GRANULARITY (1UL << ASAN_SHADOW_SHIFT) 70 71 /* Red zone size, stack and global variables are padded by ASAN_RED_ZONE_SIZE 72 up to 2 * ASAN_RED_ZONE_SIZE - 1 bytes. */ 73 #define ASAN_RED_ZONE_SIZE 32 74 75 /* Stack variable use more compact red zones. The size includes also 76 size of variable itself. */ 77 78 #define ASAN_MIN_RED_ZONE_SIZE 16 79 80 /* Shadow memory values for stack protection. Left is below protected vars, 81 the first pointer in stack corresponding to that offset contains 82 ASAN_STACK_FRAME_MAGIC word, the second pointer to a string describing 83 the frame. Middle is for padding in between variables, right is 84 above the last protected variable and partial immediately after variables 85 up to ASAN_RED_ZONE_SIZE alignment. */ 86 #define ASAN_STACK_MAGIC_LEFT 0xf1 87 #define ASAN_STACK_MAGIC_MIDDLE 0xf2 88 #define ASAN_STACK_MAGIC_RIGHT 0xf3 89 #define ASAN_STACK_MAGIC_USE_AFTER_RET 0xf5 90 #define ASAN_STACK_MAGIC_USE_AFTER_SCOPE 0xf8 91 92 #define ASAN_STACK_FRAME_MAGIC 0x41b58ab3 93 #define ASAN_STACK_RETIRED_MAGIC 0x45e0360e 94 95 #define ASAN_USE_AFTER_SCOPE_ATTRIBUTE "use after scope memory" 96 97 /* NOTE: The values below and the hooks under targetm.memtag define an ABI and 98 are hard-coded to these values in libhwasan, hence they can't be changed 99 independently here. */ 100 /* How many bits are used to store a tag in a pointer. 101 The default version uses the entire top byte of a pointer (i.e. 8 bits). */ 102 #define HWASAN_TAG_SIZE targetm.memtag.tag_size () 103 /* Tag Granule of HWASAN shadow stack. 104 This is the size in real memory that each byte in the shadow memory refers 105 to. I.e. if a variable is X bytes long in memory then its tag in shadow 106 memory will span X / HWASAN_TAG_GRANULE_SIZE bytes. 107 Most variables will need to be aligned to this amount since two variables 108 that are neighbors in memory and share a tag granule would need to share the 109 same tag (the shared tag granule can only store one tag). */ 110 #define HWASAN_TAG_GRANULE_SIZE targetm.memtag.granule_size () 111 /* Define the tag for the stack background. 112 This defines what tag the stack pointer will be and hence what tag all 113 variables that are not given special tags are (e.g. spilled registers, 114 and parameters passed on the stack). */ 115 #define HWASAN_STACK_BACKGROUND gen_int_mode (0, QImode) 116 117 /* Various flags for Asan builtins. */ 118 enum asan_check_flags 119 { 120 ASAN_CHECK_STORE = 1 << 0, 121 ASAN_CHECK_SCALAR_ACCESS = 1 << 1, 122 ASAN_CHECK_NON_ZERO_LEN = 1 << 2, 123 ASAN_CHECK_LAST = 1 << 3 124 }; 125 126 /* Flags for Asan check builtins. */ 127 #define IFN_ASAN_MARK_FLAGS DEF(POISON), DEF(UNPOISON) 128 129 enum asan_mark_flags 130 { 131 #define DEF(X) ASAN_MARK_##X 132 IFN_ASAN_MARK_FLAGS 133 #undef DEF 134 }; 135 136 /* Return true if STMT is ASAN_MARK with FLAG as first argument. */ 137 extern bool asan_mark_p (gimple *stmt, enum asan_mark_flags flag); 138 139 /* Return the size of padding needed to insert after a protected 140 decl of SIZE. */ 141 142 static inline unsigned int 143 asan_red_zone_size (unsigned int size) 144 { 145 unsigned int c = size & (ASAN_RED_ZONE_SIZE - 1); 146 return c ? 2 * ASAN_RED_ZONE_SIZE - c : ASAN_RED_ZONE_SIZE; 147 } 148 149 /* Return how much a stack variable occupis on a stack 150 including a space for red zone. */ 151 152 static inline unsigned HOST_WIDE_INT 153 asan_var_and_redzone_size (unsigned HOST_WIDE_INT size) 154 { 155 if (size <= 4) 156 return 16; 157 else if (size <= 16) 158 return 32; 159 else if (size <= 128) 160 return size + 32; 161 else if (size <= 512) 162 return size + 64; 163 else if (size <= 4096) 164 return size + 128; 165 else 166 return size + 256; 167 } 168 169 extern bool set_asan_shadow_offset (const char *); 170 171 extern bool asan_shadow_offset_set_p (); 172 173 extern void set_sanitized_sections (const char *); 174 175 extern bool asan_sanitize_stack_p (void); 176 177 extern bool asan_sanitize_allocas_p (void); 178 179 extern hash_set<tree> *asan_handled_variables; 180 181 /* Return TRUE if builtin with given FCODE will be intercepted by 182 libasan. */ 183 184 static inline bool 185 asan_intercepted_p (enum built_in_function fcode) 186 { 187 if (hwasan_sanitize_p ()) 188 return false; 189 190 return fcode == BUILT_IN_INDEX 191 || fcode == BUILT_IN_MEMCHR 192 || fcode == BUILT_IN_MEMCMP 193 || fcode == BUILT_IN_MEMCPY 194 || fcode == BUILT_IN_MEMMOVE 195 || fcode == BUILT_IN_MEMSET 196 || fcode == BUILT_IN_STRCASECMP 197 || fcode == BUILT_IN_STRCAT 198 || fcode == BUILT_IN_STRCHR 199 || fcode == BUILT_IN_STRCMP 200 || fcode == BUILT_IN_STRCPY 201 || fcode == BUILT_IN_STRDUP 202 || fcode == BUILT_IN_STRLEN 203 || fcode == BUILT_IN_STRNCASECMP 204 || fcode == BUILT_IN_STRNCAT 205 || fcode == BUILT_IN_STRNCMP 206 || fcode == BUILT_IN_STRCSPN 207 || fcode == BUILT_IN_STRPBRK 208 || fcode == BUILT_IN_STRSPN 209 || fcode == BUILT_IN_STRSTR 210 || fcode == BUILT_IN_STRNCPY; 211 } 212 213 /* Return TRUE if we should instrument for use-after-scope sanity checking. */ 214 215 static inline bool 216 asan_sanitize_use_after_scope (void) 217 { 218 return (flag_sanitize_address_use_after_scope 219 && (asan_sanitize_stack_p () || hwasan_sanitize_stack_p ())); 220 } 221 222 /* Return true if DECL should be guarded on the stack. */ 223 224 static inline bool 225 asan_protect_stack_decl (tree decl) 226 { 227 return DECL_P (decl) 228 && (!DECL_ARTIFICIAL (decl) 229 || (asan_sanitize_use_after_scope () && TREE_ADDRESSABLE (decl))); 230 } 231 232 /* Return true when flag_sanitize & FLAG is non-zero. If FN is non-null, 233 remove all flags mentioned in "no_sanitize" of DECL_ATTRIBUTES. */ 234 235 static inline bool 236 sanitize_flags_p (unsigned int flag, const_tree fn = current_function_decl) 237 { 238 unsigned int result_flags = flag_sanitize & flag; 239 if (result_flags == 0) 240 return false; 241 242 if (fn != NULL_TREE) 243 { 244 tree value = lookup_attribute ("no_sanitize", DECL_ATTRIBUTES (fn)); 245 if (value) 246 result_flags &= ~tree_to_uhwi (TREE_VALUE (value)); 247 } 248 249 return result_flags; 250 } 251 252 #endif /* TREE_ASAN */ 253