summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--util/crossgcc/patches/gcc-8.3.0_asan_shadow_offset_callback.patch109
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