public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Matthew Malcomson <Matthew.Malcomson@arm.com>
To: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Cc: "mliska@suse.cz" <mliska@suse.cz>,
	"dodji@redhat.com" <dodji@redhat.com>,	nd <nd@arm.com>,
	"kcc@google.com" <kcc@google.com>,
	"jakub@redhat.com"	<jakub@redhat.com>,
	"dvyukov@google.com" <dvyukov@google.com>
Subject: [RFC][PATCH 8/X][libsanitizer] Ensure HWASAN required alignment for stack variables
Date: Fri, 06 Sep 2019 14:46:00 -0000	[thread overview]
Message-ID: <VI1PR08MB547152251A94D540887D4D84E0BA0@VI1PR08MB5471.eurprd08.prod.outlook.com> (raw)
In-Reply-To: <156778058239.16148.17480879484406897649.scripted-patch-series@arm.com>

[-- Attachment #1: Type: text/plain, Size: 6602 bytes --]

When colouring shadow memory, we need to ensure that each tag granule
is only used by one variable at a time.

This is done by ensuring that ecah coloured variable is aligned to the
tag granule representation size and also ensure that the end of each
variable as an alignment boundary between the end and the start of any
other data stored on the stack.

This patch ensures this by adding alignment requirements in
`align_local_variable` and forcing all stack variable allocation to be
deferred to allow `expand_stack_vars` to ensure the stack pointer is
aligned before allocating any variable for the current frame.

This patch also adds some macros defining how the HWASAN shadow memory
is stored and how a tag is stored in a pointer.

gcc/ChangeLog:

2019-09-06  Matthew Malcomson  <matthew.malcomson@arm.com>

	* asan.h (HWASAN_TAG_SIZE): New macro.
	(HWASAN_TAG_GRANULE_SIZE):New macro.
	(HWASAN_SHIFT):New macro.
	(HWASAN_SHIFT_RTX):New macro.
	(HWASAN_STACK_BACKGROUND):New macro.
	* cfgexpand.c (align_local_variable): Ensure alignment.
	(expand_stack_vars): Ensure alignment.
	(defer_stack_allocation): Ensure all variables are deferred so
	they can be handled by `expand_stack_vars`.



###############     Attachment also inlined for ease of reply    ###############


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 <tree> *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
+   addtag<mode>4 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


[-- Attachment #2: hwasan-implementation07.patch --]
[-- Type: text/plain, Size: 5176 bytes --]

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 <tree> *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
+   addtag<mode>4 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


  parent reply	other threads:[~2019-09-06 14:46 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-06 14:46 [Patch 0/X] [WIP][RFC][libsanitizer] Introduce HWASAN to GCC Matthew Malcomson
2019-09-06 14:46 ` [RFC][PATCH 1/X][libsanitizer] Introduce libsanitizer to GCC tree Matthew Malcomson
2019-09-09  9:26   ` Martin Liška
2019-09-06 14:46 ` [RFC][PATCH 14/X][libsanitizer] Introduce HWASAN block-scope poisoning Matthew Malcomson
2019-09-06 14:46 ` [RFC][PATCH 5/X][libsanitizer] Introduce longjmp/setjmp interceptors to libhwasan Matthew Malcomson
2019-09-09 10:02   ` Martin Liška
2019-09-09 10:29     ` Matthew Malcomson
2019-09-09 10:49       ` Martin Liška
2019-09-06 14:46 ` Matthew Malcomson [this message]
2019-09-06 14:46 ` [RFC][PATCH 7/X][libsanitizer] Add option to bootstrap using HWASAN Matthew Malcomson
2019-09-06 14:46 ` [RFC][PATCH 4/X][libsanitizer] Pass size and pointer info to error reporting functions Matthew Malcomson
2019-09-09  9:27   ` Martin Liška
2019-09-06 14:46 ` [RFC][PATCH 2/X][libsanitizer] Tie the hwasan library into our build system Matthew Malcomson
2019-09-06 14:46 ` [RFC][PATCH 3/X][libsanitizer] Allow compilation for HWASAN_WITH_INTERCEPTORS=OFF Matthew Malcomson
2019-09-09  9:27   ` Martin Liška
2019-09-06 14:47 ` [RFC][PATCH 9/X][libsanitizer] Put tags into each stack variable pointer Matthew Malcomson
2019-09-06 14:47 ` [RFC][PATCH 6/X][libsanitizer] Add -fsanitize=hwaddress flags Matthew Malcomson
2019-09-09 10:06   ` Martin Liška
2019-09-09 10:18     ` Matthew Malcomson
2019-09-09 10:20       ` Martin Liška
2019-09-06 14:47 ` [RFC][PATCH 12/X][libsanitizer] Check pointer tags match address tags Matthew Malcomson
2019-09-06 14:47 ` [RFC][PATCH 11/X][libsanitizer] Uncolour stack frame on function exit Matthew Malcomson
2019-09-06 14:47 ` [RFC][PATCH 15/X][libsanitizer] Add in MTE stubs Matthew Malcomson
2019-09-06 14:47 ` [RFC][PATCH 16/X][libsanitizer] Build libhwasan with interceptors Matthew Malcomson
2019-09-06 14:47 ` [RFC][PATCH 10/X][libsanitizer] Colour the shadow stack for each stack variable Matthew Malcomson
2019-09-06 14:47 ` [RFC][PATCH 13/X][libsanitizer] Instrument known builtin function calls Matthew Malcomson
2019-09-09 10:47 ` [Patch 0/X] [WIP][RFC][libsanitizer] Introduce HWASAN to GCC Martin Liška
2019-09-09 15:55   ` Matthew Malcomson
2019-09-10  1:06     ` Kostya Serebryany via gcc-patches
2019-09-11 11:53     ` Martin Liška
2019-09-11 16:37       ` Matthew Malcomson
2019-09-11 18:34         ` Evgenii Stepanov via gcc-patches
2019-09-23  8:02 ` Martin Liška
2019-10-23 11:02   ` Matthew Malcomson
2019-10-24 10:11     ` Martin Liška

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=VI1PR08MB547152251A94D540887D4D84E0BA0@VI1PR08MB5471.eurprd08.prod.outlook.com \
    --to=matthew.malcomson@arm.com \
    --cc=dodji@redhat.com \
    --cc=dvyukov@google.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=kcc@google.com \
    --cc=mliska@suse.cz \
    --cc=nd@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).