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 --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. -- 2.43.0