diff mbox series

[RFC,4/9] opts: doc: aarch64: add new memtag sanitizer

Message ID 20241107213937.362703-5-indu.bhagat@oracle.com
State New
Headers show
Series Add -fsanitize=memtag | expand

Commit Message

Indu Bhagat Nov. 7, 2024, 9:39 p.m. UTC
Add new command line option -fsanitize=memtag with the following
new params:
 --param memtag-instrument-stack [0,1] (default 1) to use MTE
insns for enabling dynamic checking of stack variables.
 --param memtag-instrument-alloca [0,1] (default 1) to use MTE
insns for enabling dynamic checking of stack allocas.

Add errors to convey that memtag sanitizer does not work with
hwaddress and address sanitizers.  Also error out if memtag ISA
extension is not enabled.

MEMTAG sanitizer will use the HWASAN machinery, but with a few
differences:
  - The tags are always generated at runtime by the hardware, so
    -fsanitize=memtag enforces a --param hwasan-random-frame-tag=1

Add documentation in gcc/doc/invoke.texi.

TBD:
  - Add new command line option -fsanitize-memtag-mode=str, where str
    can be sync, async or asymm (see
    https://docs.kernel.org/arch/arm64/memory-tagging-extension.html).  This
    option will not affect code generation; the information will eventually
    be need to be passed to perhaps the linker.  This is contingent on
    what ABI we define between userspace applications and the kernel for
    communicating that the stack be PROT_MTE.

gcc/
        * builtins.def: Adjust the macro to include the new
	SANTIZIE_MEMTAG.
        * flag-types.h (enum sanitize_code): Add new enumerator for
	ANITIZE_MEMTAG.
        * opts.cc (finish_options): MEMTAG conflicts with hwaddress and
	address sanitizers.
        (common_handle_option): SANITIZE_MEMTAG tags are always
	generated (randomly) by the hardware.
        * params.opt: Add new params for MEMTAG sanitizer.
doc/
	* invoke.texi: Update documentation.

gcc/config/
        * aarch64/aarch64.cc (aarch64_override_options_internal): Error
	out if MTE is not available.
---
 gcc/builtins.def              |  1 +
 gcc/config/aarch64/aarch64.cc |  4 ++++
 gcc/doc/invoke.texi           | 11 +++++++++--
 gcc/flag-types.h              |  2 ++
 gcc/opts.cc                   | 15 +++++++++++++++
 gcc/params.opt                |  8 ++++++++
 6 files changed, 39 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/gcc/builtins.def b/gcc/builtins.def
index 0c76ebc5e31a..659c7c2b5c13 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -245,6 +245,7 @@  along with GCC; see the file COPYING3.  If not see
 	       true, true, true, ATTRS, true, \
 	      (flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \
 				| SANITIZE_HWADDRESS \
+				| SANITIZE_MEMTAG \
 				| SANITIZE_UNDEFINED \
 				| SANITIZE_UNDEFINED_NONDEFAULT) \
 	       || flag_sanitize_coverage))
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index f2b53475adbe..1ef2dbcf9030 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -18518,6 +18518,10 @@  aarch64_override_options_internal (struct gcc_options *opts)
       && !fixed_regs[R18_REGNUM])
     error ("%<-fsanitize=shadow-call-stack%> requires %<-ffixed-x18%>");
 
+  if (flag_sanitize & SANITIZE_MEMTAG && !TARGET_MEMTAG)
+    error ("%<-fsanitize=memtag%> requires the ISA extension %qs",
+	   "memtag");
+
   aarch64_feature_flags isa_flags = aarch64_get_isa_flags (opts);
   if ((isa_flags & (AARCH64_FL_SM_ON | AARCH64_FL_ZA_ON))
       && !(isa_flags & AARCH64_FL_SME))
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 7146163d66d0..f8bd273b07ad 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -17626,8 +17626,9 @@  the available options are shown at startup of the instrumented program.  See
 @url{https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags}
 for a list of supported options.
 The option cannot be combined with @option{-fsanitize=thread} or
-@option{-fsanitize=hwaddress}.  Note that the only target
-@option{-fsanitize=hwaddress} is currently supported on is AArch64.
+@option{-fsanitize=hwaddress} or @option{-fsanitize=memtag}.  Note that the
+only target @option{-fsanitize=hwaddress} and @option{-fsanitize=memtag} are
+currently supported on is AArch64.
 
 To get more accurate stack traces, it is possible to use options such as
 @option{-O0}, @option{-O1}, or @option{-Og} (which, for instance, prevent
@@ -17676,6 +17677,12 @@  possible by specifying the command-line options
 @option{--param hwasan-instrument-allocas=1} respectively. Using a random frame
 tag is not implemented for kernel instrumentation.
 
+@opindex fsanitize=memtag
+@item -fsanitize=memtag
+Use Memory Tagging Extension instructions instead of instrumentation to allow
+the detection of memory errors.  This option is available only on those AArch64
+architectures that support Memory Tagging Extensions.
+
 @opindex fsanitize=pointer-compare
 @item -fsanitize=pointer-compare
 Instrument comparison operation (<, <=, >, >=) with pointer operands.
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index df56337f7e84..3f4f4f13570f 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -330,6 +330,8 @@  enum sanitize_code {
   SANITIZE_KERNEL_HWADDRESS = 1UL << 30,
   /* Shadow Call Stack.  */
   SANITIZE_SHADOW_CALL_STACK = 1UL << 31,
+  /* Memory Tagging.  */
+  SANITIZE_MEMTAG = 1ULL << 32,
   SANITIZE_SHIFT = SANITIZE_SHIFT_BASE | SANITIZE_SHIFT_EXPONENT,
   SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE
 		       | SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN
diff --git a/gcc/opts.cc b/gcc/opts.cc
index 089e5e019db3..d0e28ce987c6 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -1290,6 +1290,13 @@  finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
   report_conflicting_sanitizer_options (opts, loc, SANITIZE_USER_ADDRESS,
 					SANITIZE_KERNEL_ADDRESS);
 
+  /* Sanitizers using Memory-Tagging Extension conflict with HWASAN and
+     ASAN.  */
+  report_conflicting_sanitizer_options (opts, loc, SANITIZE_MEMTAG,
+					SANITIZE_HWADDRESS);
+  report_conflicting_sanitizer_options (opts, loc, SANITIZE_MEMTAG,
+					SANITIZE_ADDRESS);
+
   /* Check error recovery for -fsanitize-recover option.  */
   for (int i = 0; sanitizer_opts[i].name != NULL; ++i)
     if ((opts->x_flag_sanitize_recover & sanitizer_opts[i].flag)
@@ -2148,6 +2155,7 @@  const struct sanitizer_opts_s sanitizer_opts[] =
   SANITIZER_OPT (pointer-overflow, SANITIZE_POINTER_OVERFLOW, true, true),
   SANITIZER_OPT (builtin, SANITIZE_BUILTIN, true, true),
   SANITIZER_OPT (shadow-call-stack, SANITIZE_SHADOW_CALL_STACK, false, false),
+  SANITIZER_OPT (memtag, SANITIZE_MEMTAG, false, false),
   SANITIZER_OPT (all, ~0U, true, true),
 #undef SANITIZER_OPT
   { NULL, 0U, 0UL, false, false }
@@ -2782,6 +2790,13 @@  common_handle_option (struct gcc_options *opts,
 	  SET_OPTION_IF_UNSET (opts, opts_set,
 			       param_hwasan_instrument_allocas, 0);
 	}
+      /* Memtag sanitizer implies HWASAN but with tags always generated by the
+	 hardware randomly.  */
+      if (opts->x_flag_sanitize & SANITIZE_MEMTAG)
+	{
+	  SET_OPTION_IF_UNSET (opts, opts_set,
+			       param_hwasan_random_frame_tag, 1);
+	}
       break;
 
     case OPT_fsanitize_recover_:
diff --git a/gcc/params.opt b/gcc/params.opt
index 7c572774df24..a87df398a742 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -90,6 +90,14 @@  Enable hwasan instrumentation of store operations.
 Common Joined UInteger Var(param_hwasan_instrument_mem_intrinsics) Init(1) IntegerRange(0, 1) Param Optimization
 Enable hwasan instrumentation of builtin functions.
 
+-param=memtag-instrument-stack=
+Target Joined UInteger Var(param_memtag_instrument_stack) Init(1) IntegerRange(0, 1) Param
+When sanitizing using MTE instructions, add checks for all stack automatics.
+
+-param=memtag-instrument-allocas=
+Target Joined UInteger Var(param_memtag_instrument_allocas) Init(1) IntegerRange(0, 1) Param
+When sanitizing using MTE instructions, add checks for all stack allocas.
+
 -param=avg-loop-niter=
 Common Joined UInteger Var(param_avg_loop_niter) Init(10) IntegerRange(1, 65536) Param Optimization
 Average number of iterations of a loop.