Skip to content
Snippets Groups Projects
Commit 93a73251 authored by Matthew Malcomson's avatar Matthew Malcomson
Browse files

libsanitizer: Add hwasan pass and associated gimple changes

There are four main features to this change:

1) Check pointer tags match address tags.

When sanitizing for hwasan we now put HWASAN_CHECK internal functions before
memory accesses in the `asan` pass.  This checks that a tag in the pointer
being used match the tag stored in shadow memory for the memory region being
used.

These internal functions are expanded into actual checks in the sanopt
pass that happens just before expansion into RTL.

We use the same mechanism that currently inserts ASAN_CHECK internal
functions to insert the new HWASAN_CHECK functions.

2) Instrument known builtin function calls.

Handle all builtin functions that we know use memory accesses.
This commit uses the machinery added for ASAN to identify builtin
functions that access memory.

The main differences between the approaches for HWASAN and ASAN are:
 - libhwasan intercepts much less builtin functions.
 - Alloca needs to be transformed differently (instead of adding
   redzones it needs to tag shadow memory and return a tagged pointer).
 - stack_restore needs to untag the shadow stack between the current
   position and where it's going.
 - `noreturn` functions can not be handled by simply unpoisoning the
   entire shadow stack -- there is no "always valid" tag.
   (exceptions and things such as longjmp need to be handled in a
   different way, usually in the runtime).

For hardware implemented checking (such as AArch64's memory tagging
extension) alloca and stack_restore will need to be handled by hooks in
the backend rather than transformation at the gimple level.  This will
allow architecture specific handling of such stack modifications.

3) Introduce HWASAN block-scope poisoning

Here we use exactly the same mechanism as ASAN_MARK to poison/unpoison
variables on entry/exit of a block.

In order to simply use the exact same machinery we're using the same
internal functions until the SANOPT pass.  This means that all handling
of ASAN_MARK is the same.
This has the negative that the naming may be a little confusing, but a
positive that handling of the internal function doesn't have to be
duplicated for a function that behaves exactly the same but has a
different name.

gcc/ChangeLog:

	* asan.c (asan_instrument_reads): New.
	(asan_instrument_writes): New.
	(asan_memintrin): New.
	(handle_builtin_stack_restore): Account for HWASAN.
	(handle_builtin_alloca): Account for HWASAN.
	(get_mem_refs_of_builtin_call): Special case strlen for HWASAN.
	(hwasan_instrument_reads): New.
	(hwasan_instrument_writes): New.
	(hwasan_memintrin): New.
	(report_error_func): Assert not HWASAN.
	(build_check_stmt): Make HWASAN_CHECK instead of ASAN_CHECK.
	(instrument_derefs): HWASAN does not tag globals.
	(instrument_builtin_call): Use new helper functions.
	(maybe_instrument_call): Don't instrument `noreturn` functions.
	(initialize_sanitizer_builtins): Add new type.
	(asan_expand_mark_ifn): Account for HWASAN.
	(asan_expand_check_ifn): Assert never called by HWASAN.
	(asan_expand_poison_ifn): Account for HWASAN.
	(asan_instrument): Branch based on whether using HWASAN or ASAN.
	(pass_asan::gate): Return true if sanitizing HWASAN.
	(pass_asan_O0::gate): Return true if sanitizing HWASAN.
	(hwasan_check_func): New.
	(hwasan_expand_check_ifn): New.
	(hwasan_expand_mark_ifn): New.
	(gate_hwasan): New.
	* asan.h (hwasan_expand_check_ifn): New decl.
	(hwasan_expand_mark_ifn): New decl.
	(gate_hwasan): New decl.
	(asan_intercepted_p): Always false for hwasan.
	(asan_sanitize_use_after_scope): Account for HWASAN.
	* builtin-types.def (BT_FN_PTR_CONST_PTR_UINT8): New.
	* gimple-fold.c (gimple_build): New overload for building function
	calls without arguments.
	(gimple_build_round_up): New.
	* gimple-fold.h (gimple_build): New decl.
	(gimple_build): New inline function.
	(gimple_build_round_up): New decl.
	(gimple_build_round_up): New inline function.
	* gimple-pretty-print.c (dump_gimple_call_args): Account for
	HWASAN.
	* gimplify.c (asan_poison_variable): Account for HWASAN.
	(gimplify_function_tree): Remove requirement of
	SANITIZE_ADDRESS, requiring asan or hwasan is accounted for in
	`asan_sanitize_use_after_scope`.
	* internal-fn.c (expand_HWASAN_CHECK): New.
	(expand_HWASAN_ALLOCA_UNPOISON): New.
	(expand_HWASAN_CHOOSE_TAG): New.
	(expand_HWASAN_MARK): New.
	(expand_HWASAN_SET_TAG): New.
	* internal-fn.def (HWASAN_ALLOCA_UNPOISON): New.
	(HWASAN_CHOOSE_TAG): New.
	(HWASAN_CHECK): New.
	(HWASAN_MARK): New.
	(HWASAN_SET_TAG): New.
	* sanitizer.def (BUILT_IN_HWASAN_LOAD1): New.
	(BUILT_IN_HWASAN_LOAD2): New.
	(BUILT_IN_HWASAN_LOAD4): New.
	(BUILT_IN_HWASAN_LOAD8): New.
	(BUILT_IN_HWASAN_LOAD16): New.
	(BUILT_IN_HWASAN_LOADN): New.
	(BUILT_IN_HWASAN_STORE1): New.
	(BUILT_IN_HWASAN_STORE2): New.
	(BUILT_IN_HWASAN_STORE4): New.
	(BUILT_IN_HWASAN_STORE8): New.
	(BUILT_IN_HWASAN_STORE16): New.
	(BUILT_IN_HWASAN_STOREN): New.
	(BUILT_IN_HWASAN_LOAD1_NOABORT): New.
	(BUILT_IN_HWASAN_LOAD2_NOABORT): New.
	(BUILT_IN_HWASAN_LOAD4_NOABORT): New.
	(BUILT_IN_HWASAN_LOAD8_NOABORT): New.
	(BUILT_IN_HWASAN_LOAD16_NOABORT): New.
	(BUILT_IN_HWASAN_LOADN_NOABORT): New.
	(BUILT_IN_HWASAN_STORE1_NOABORT): New.
	(BUILT_IN_HWASAN_STORE2_NOABORT): New.
	(BUILT_IN_HWASAN_STORE4_NOABORT): New.
	(BUILT_IN_HWASAN_STORE8_NOABORT): New.
	(BUILT_IN_HWASAN_STORE16_NOABORT): New.
	(BUILT_IN_HWASAN_STOREN_NOABORT): New.
	(BUILT_IN_HWASAN_TAG_MISMATCH4): New.
	(BUILT_IN_HWASAN_HANDLE_LONGJMP): New.
	(BUILT_IN_HWASAN_TAG_PTR): New.
	* sanopt.c (sanopt_optimize_walker): Act for hwasan.
	(pass_sanopt::execute): Act for hwasan.
	* toplev.c (compile_file): Use `gate_hwasan` function.
parent 0854b584
No related branches found
No related tags found
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment