diff options
Diffstat (limited to 'util/crossgcc')
-rw-r--r-- | util/crossgcc/patches/gcc-8.3.0_asan_shadow_offset_callback.patch | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/util/crossgcc/patches/gcc-8.3.0_asan_shadow_offset_callback.patch b/util/crossgcc/patches/gcc-8.3.0_asan_shadow_offset_callback.patch new file mode 100644 index 0000000000..975cad8e1b --- /dev/null +++ b/util/crossgcc/patches/gcc-8.3.0_asan_shadow_offset_callback.patch @@ -0,0 +1,109 @@ +From 41a82fb711f3637b4b7f57756492b628058f9d5f Mon Sep 17 00:00:00 2001 +From: Harshit Sharma <harshitsharmajs@gmail.com> +Date: Fri, 10 Jul 2020 13:06:08 -0700 +Subject: [PATCH] crossgcc: Enable GCC to get asan shadow offset at runtime + +Unlike Linux kernel which has a static shadow region layout, we have multiple stages in +coreboot and thus require a different shadow offset address. Unfortunately, GCC currently +only supports adding a static shadow offset at compile time using -fasan-shadow-offset flag. + +For this reason, we enable GCC to determine asan shadow offset address at runtime using a +callback function named __asan_shadow_offset(). This supersedes the need to specify this +address at compile time. GCC then makes use of this shadow offset to protect stack buffers +by inserting red zones around them. + +Some other benefits of having this GCC patch are: +a. We can place the shadow region in a separate linker section with all its advantages like + automatic fit insurance. This ensures if a platform doesn't have enough memory space to + hold shadow region, the build will fail. (However, if we use a fixed shadow offset on a + platform that actually doesn't have enough memory, it may still build without any errors.) +b. We don't modify the memory layout compared to the current one, as we are placing the + shadow region at the end of the space already occupied by the program. +c. We can be much more flexible later if needed (thinking of other stages like bootblock). +d. Since we are appending the shadow buffer to the region already occupied, we make efficient + use of the limited memory available which is highly beneficial when using cache as ram. + +Further, we have made sure that if you compile you tree with ASan enabled but missed this +patch, it will end up in the following compilation error: +"invalid --param name 'asan-use-shadow-offset-callback'" +So, you cannot accidentally enable the feature without having your compiler patched. + +Signed-off-by: Harshit Sharma <harshitsharmajs@gmail.com> +--- + gcc/asan.c | 29 ++++++++++++++++++++++------- + gcc/params.def | 6 ++++++ + gcc/params.h | 2 ++ + 3 files changed, 30 insertions(+), 7 deletions(-) + +diff --git a/gcc/asan.c b/gcc/asan.c +index 235e21947..713bf994d 100644 +--- a/gcc/asan.c ++++ b/gcc/asan.c +@@ -1389,13 +1389,28 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, + TREE_ASM_WRITTEN (decl) = 1; + TREE_ASM_WRITTEN (id) = 1; + emit_move_insn (mem, expand_normal (build_fold_addr_expr (decl))); +- shadow_base = expand_binop (Pmode, lshr_optab, base, +- gen_int_shift_amount (Pmode, ASAN_SHADOW_SHIFT), +- NULL_RTX, 1, OPTAB_DIRECT); +- shadow_base +- = plus_constant (Pmode, shadow_base, +- asan_shadow_offset () +- + (base_align_bias >> ASAN_SHADOW_SHIFT)); ++ if (ASAN_USE_SHADOW_OFFSET_CALLBACK) { ++ rtx addr, shadow_offset_rtx; ++ ret = init_one_libfunc ("__asan_shadow_offset"); ++ addr= convert_memory_address (ptr_mode, base); ++ ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode, ++ addr, ptr_mode); ++ shadow_offset_rtx = convert_memory_address (Pmode, ret); ++ shadow_base = expand_binop (Pmode, lshr_optab, base, ++ gen_int_shift_amount (Pmode, ASAN_SHADOW_SHIFT), ++ NULL_RTX, 1, OPTAB_DIRECT); ++ shadow_base = expand_binop (Pmode, add_optab, shadow_base, ++ shadow_offset_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN); ++ shadow_base = plus_constant (Pmode, shadow_base, ++ (base_align_bias >> ASAN_SHADOW_SHIFT)); ++ } else { ++ shadow_base = expand_binop (Pmode, lshr_optab, base, ++ gen_int_shift_amount (Pmode, ASAN_SHADOW_SHIFT), ++ NULL_RTX, 1, OPTAB_DIRECT); ++ shadow_base = plus_constant (Pmode, shadow_base, ++ asan_shadow_offset () ++ + (base_align_bias >> ASAN_SHADOW_SHIFT)); ++ } + gcc_assert (asan_shadow_set != -1 + && (ASAN_RED_ZONE_SIZE >> ASAN_SHADOW_SHIFT) == 4); + shadow_mem = gen_rtx_MEM (SImode, shadow_base); +diff --git a/gcc/params.def b/gcc/params.def +index dad47ec2b..bfe6eaa0b 100644 +--- a/gcc/params.def ++++ b/gcc/params.def +@@ -1203,6 +1203,12 @@ DEFPARAM (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, + "in function becomes greater or equal to this number.", + 7000, 0, INT_MAX) + ++DEFPARAM (PARAM_ASAN_USE_SHADOW_OFFSET_CALLBACK, ++ "asan-use-shadow-offset-callback", ++ "Use shadow offset callback function at runtime instead of " ++ "fixed value at compile time at the cost of runtime overhead.", ++ 0, 0, 1) ++ + DEFPARAM (PARAM_USE_AFTER_SCOPE_DIRECT_EMISSION_THRESHOLD, + "use-after-scope-direct-emission-threshold", + "Use direct poisoning/unpoisoning instructions for variables " +diff --git a/gcc/params.h b/gcc/params.h +index 98249d2a1..d3bd6be38 100644 +--- a/gcc/params.h ++++ b/gcc/params.h +@@ -246,6 +246,8 @@ extern void init_param_values (int *params); + PARAM_VALUE (PARAM_ASAN_USE_AFTER_RETURN) + #define ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD \ + PARAM_VALUE (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD) ++#define ASAN_USE_SHADOW_OFFSET_CALLBACK \ ++ PARAM_VALUE (PARAM_ASAN_USE_SHADOW_OFFSET_CALLBACK) + #define ASAN_PARAM_USE_AFTER_SCOPE_DIRECT_EMISSION_THRESHOLD \ + ((unsigned) PARAM_VALUE (PARAM_USE_AFTER_SCOPE_DIRECT_EMISSION_THRESHOLD)) + +-- +2.17.1 |