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. 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. --- [Changes from RFC V1] - Added documentation for memtag-instrument-stack and memtag-instrument-allocas. [End of changes from RFC V1] --- gcc/builtins.def | 1 + gcc/config/aarch64/aarch64.cc | 4 ++++ gcc/doc/invoke.texi | 19 +++++++++++++++++-- gcc/flag-types.h | 2 ++ gcc/opts.cc | 15 +++++++++++++++ gcc/params.opt | 8 ++++++++ 6 files changed, 47 insertions(+), 2 deletions(-) diff --git a/gcc/builtins.def b/gcc/builtins.def index ff470051e54e..1f52eb56d962 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -253,6 +253,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 4e801146c60a..362de36dd098 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -18752,6 +18752,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 ffde9df85fd3..de651183a703 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -17079,6 +17079,14 @@ and @option{-fsanitize=kernel-hwaddress}. To disable instrumentation of builtin functions use @option{--param hwasan-instrument-mem-intrinsics=0}. +@item memtag-instrument-stack +Enable MTE tagging of statically sized stack-allocated variables. This kind of +code generation is enabled by default when using @option{-fsanitize=memtag}. + +@item memtag-instrument-allocas +Enable MTE tagging of dynamically sized stack-allocated variables. This kind of +code generation is enabled by default when using @option{-fsanitize=memtag}. + @item use-after-scope-direct-emission-threshold If the size of a local variable in bytes is smaller or equal to this number, directly poison (or unpoison) shadow memory instead of using @@ -17963,8 +17971,9 @@ for a list of supported options. The option cannot be combined with @option{-fsanitize=thread} or @option{-fsanitize=hwaddress}. Note that the only targets @option{-fsanitize=hwaddress} is currently supported on are x86-64 -(only with @code{-mlam=u48} or @code{-mlam=u57} options) and AArch64, -in both cases only in ABIs with 64-bit pointers. +(only with @code{-mlam=u48} or @code{-mlam=u57} options) and AArch64, in both +cases only in ABIs with 64-bit pointers. Similarly, @option{-fsanitize=memtag} +is currently only supported on AArch64 ABIs with 64-bit pointers. When compiling with @option{-fsanitize=address}, you should also use @option{-g} to produce more meaningful output. @@ -18017,6 +18026,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 01276986874a..77c364a5c745 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -337,6 +337,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 86c6691ecec4..00db662c32ef 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -1287,6 +1287,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) @@ -2146,6 +2153,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 } @@ -2780,6 +2788,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 422d082b3557..77ece0c50512 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -94,6 +94,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