From: Indu Bhagat <indu.bha...@oracle.com> Add new command line option -fsanitize=memtag-stack with the following new params: --param memtag-instrument-alloca [0,1] (default 1) to use MTE insns for enabling dynamic checking of stack allocas.
Along with the new SANITIZE_MEMTAG_STACK, define a SANITIZE_MEMTAG which will be set if any kind of memtag sanitizer is in effect (e.g., later we may add -fsanitize=memtag-globals). 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-stack 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_STACK. * flag-types.h (enum sanitize_code): Add new enumerator for SANITIZE_MEMTAG and SANITIZE_MEMTAG_STACK. * opts.cc (finish_options): memtag-stack sanitizer conflicts with hwaddress and address sanitizers. (sanitizer_opts): Add new memtag-stack sanitizer. (parse_sanitizer_options): memtag-stack sanitizer cannot recover. * params.opt: Add new params for memtag-stack sanitizer. doc/ * invoke.texi: Update documentation. Signed-off-by: Claudiu Zissulescu <claudiu.zissulescu-iancule...@oracle.com> --- gcc/builtins.def | 1 + gcc/doc/invoke.texi | 13 ++++++++++++- gcc/flag-types.h | 4 ++++ gcc/opts.cc | 22 +++++++++++++++++++++- gcc/params.opt | 4 ++++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/gcc/builtins.def b/gcc/builtins.def index d7b2894bcfa..5f0b1107347 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -257,6 +257,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_STACK \ | SANITIZE_UNDEFINED \ | SANITIZE_UNDEFINED_NONDEFAULT) \ || flag_sanitize_coverage)) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 74f5ee26042..d8f11201361 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -17261,7 +17261,7 @@ When using stack instrumentation, decide tags for stack variables using a deterministic sequence beginning at a random tag for each frame. With this parameter unset tags are chosen using the same sequence but beginning from 1. This is enabled by default for @option{-fsanitize=hwaddress} and unavailable -for @option{-fsanitize=kernel-hwaddress}. +for @option{-fsanitize=kernel-hwaddress} and @option{-fsanitize=memtag-stack}. To disable it use @option{--param hwasan-random-frame-tag=0}. @item hwasan-instrument-allocas @@ -17294,6 +17294,11 @@ and @option{-fsanitize=kernel-hwaddress}. To disable instrumentation of builtin functions use @option{--param hwasan-instrument-mem-intrinsics=0}. +@item memtag-instrument-allocas +Enable hardware-assisted memory tagging of dynamically sized stack-allocated +variables. This kind of code generation is enabled by default when using +@option{-fsanitize=memtag-stack}. + @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 @@ -18225,6 +18230,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-stack +@item -fsanitize=memtag-stack +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 9a3cc4a2e16..0c9c863a654 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -337,6 +337,10 @@ enum sanitize_code { SANITIZE_KERNEL_HWADDRESS = 1UL << 30, /* Shadow Call Stack. */ SANITIZE_SHADOW_CALL_STACK = 1UL << 31, + /* Memory Tagging for Stack. */ + SANITIZE_MEMTAG_STACK = 1ULL << 32, + /* Memory Tagging. */ + SANITIZE_MEMTAG = SANITIZE_MEMTAG_STACK, 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 d00e05f6321..b4f516fdce6 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -1307,6 +1307,24 @@ 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); + + /* Memtag sanitizer implies HWASAN but with tags always generated by + the hardware randomly. */ + if ((opts->x_flag_sanitize & SANITIZE_MEMTAG_STACK) + && opts->x_param_hwasan_random_frame_tag == 0) + { + warning_at (loc, OPT_fsanitize_, + "%<--param hwasan-random-frame-tag=0%> is ignored when " + "%<-fsanitize=memtag-stack%> is present"); + opts->x_param_hwasan_random_frame_tag = 1; + } + /* 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) @@ -2161,6 +2179,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-stack, SANITIZE_MEMTAG_STACK, false, false), SANITIZER_OPT (all, ~0ULL, true, true), #undef SANITIZER_OPT { NULL, 0ULL, 0UL, false, false } @@ -2299,7 +2318,8 @@ parse_sanitizer_options (const char *p, location_t loc, int scode, else if (code == OPT_fsanitize_recover_) flags |= ~(SANITIZE_THREAD | SANITIZE_LEAK | SANITIZE_UNREACHABLE | SANITIZE_RETURN - | SANITIZE_SHADOW_CALL_STACK); + | SANITIZE_SHADOW_CALL_STACK + | SANITIZE_MEMTAG_STACK); else /* if (code == OPT_fsanitize_trap_) */ flags |= (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT); diff --git a/gcc/params.opt b/gcc/params.opt index 31aa0bd5753..570e9df9a72 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -94,6 +94,10 @@ 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-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.50.0