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