diff --git a/gcc/asan.h b/gcc/asan.h index 66c11139b5ccbe307850d0be57e86f96445dd18d..d78f6b821c7d1e859cc53f124e071eac27a5e9b8 100644 --- a/gcc/asan.h +++ b/gcc/asan.h @@ -75,6 +75,41 @@ extern hash_set *asan_used_labels; #define ASAN_USE_AFTER_SCOPE_ATTRIBUTE "use after scope memory" +/* NOTE: The macros below are hard-coded to these values in libhwasan, and + hence can't be changed independently here. */ +/* How many bits are used to store a tag in a pointer. + For aarch64 MTE we have 4 bits per colour. + AArch64 has a Top-Byte-Ignore feature that allows the use of the top byte of + pointers for storing information, HWASAN can use that entire top byte if + required. + If changing this value, be careful of the predicates/constraints on the + addtag4 patterns in the backend. */ +#define HWASAN_TAG_SIZE 4 +/* Tag Granule of HWASAN shadow stack. + This is the size in real memory that each byte in the shadow memory refers + to. I.e. if a variable is X bytes long in memory then it's colour in shadow + memory will span X / HWASAN_TAG_GRANULE_SIZE bytes. + On top of this, most variables will need to be aligned to this amount since + two variables that are neighbours in memory and share a tag granule would + need to share the same colour (as the shared tag granule can only store one + colour). */ +#define HWASAN_TAG_GRANULE_SIZE (1ULL << HWASAN_TAG_SIZE) +/* How many bits to shift in order to access the tag bits. + This approach assumes that the tag is stored in the top N bits of a pointer, + and hence that shifting a known amount will leave just the tag bits. */ +#define HWASAN_SHIFT 56 +#define HWASAN_SHIFT_RTX const_int_rtx[MAX_SAVED_CONST_INT + HWASAN_SHIFT] +/* Define the tag for the stack background. + NOTE: Having a background colour of zero is hard-coded in the runtime + library, so we can't really change this. + This defines what colour the stack pointer will be and hence what colour all + uncoloured parts of the stack are (e.g. spilled registers). + It also provides a tag for stack allocation to avoid, since an object stored + on the stack will want to have a different colour to the background stack to + ensure things like the return address etc can't be affected by accesses + through pointer to a user-object. */ +#define HWASAN_STACK_BACKGROUND 0 + /* Various flags for Asan builtins. */ enum asan_check_flags { diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 7722dcd4004e270551c8bcd4403e53a78ebfdff0..c5585d83c6e155856e7a4278e21c35ee5675bbdd 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -372,7 +372,14 @@ align_local_variable (tree decl) align = LOCAL_DECL_ALIGNMENT (decl); SET_DECL_ALIGN (decl, align); } - return align / BITS_PER_UNIT; + + unsigned int ret_align = align / BITS_PER_UNIT; + + if (memory_tagging_p ()) + ret_align = ret_align > HWASAN_TAG_GRANULE_SIZE + ? ret_align + : HWASAN_TAG_GRANULE_SIZE; + return ret_align; } /* Align given offset BASE with ALIGN. Truncate up if ALIGN_UP is true, @@ -1117,6 +1124,29 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) alignb = stack_vars[i].alignb; if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT) { + if (memory_tagging_p ()) + { + /* Allocate zero bytes to take advantage of the + alloc_stack_frame_space logic of ensuring the stack is aligned + despite having poly_int64's to deal with. + + There must be no tag granule "shared" between different + objects. This means that no HWASAN_TAG_GRANULE_SIZE byte + chunk can have more than one object in it. + + We ensure this by forcing the end of the last bit of data to + be aligned to HWASAN_TAG_GRANULE_SIZE bytes here, and setting + the start of each variable to be aligned to + HWASAN_TAG_GRANULE_SIZE bytes in `align_local_variable`. + + We can't align just one of the start or end, since there are + untagged things stored on the stack that we have no control on + the alignment (e.g. function parameters which must conform to + ABI requirements) and these can't share a tag granule with a + tagged variable. */ + gcc_assert (stack_vars[i].alignb >= HWASAN_TAG_GRANULE_SIZE); + alloc_stack_frame_space (0, HWASAN_TAG_GRANULE_SIZE); + } base = virtual_stack_vars_rtx; /* ASAN description strings don't yet have a syntax for expressing polynomial offsets. */ @@ -1545,8 +1575,11 @@ defer_stack_allocation (tree var, bool toplevel) /* If stack protection is enabled, *all* stack variables must be deferred, so that we can re-order the strings to the top of the frame. - Similarly for Address Sanitizer. */ - if (flag_stack_protect || asan_sanitize_stack_p ()) + Similarly for Address Sanitizer. + When memory tagging we defer all stack variables so we can handle them in + one place (handle here meaning ensure aligned and record information on + its position on the stack). */ + if (flag_stack_protect || asan_sanitize_stack_p () || memory_tagging_p ()) return true; unsigned int align = TREE_CODE (var) == SSA_NAME