Add support for dynamic shadow offset

Message ID CAAAgQ183kaXuGqK27xqtw2fY-O0XKJOYYvXX3fVFxfqmzdbgsw@mail.gmail.com
State New
Headers show
Series
  • Add support for dynamic shadow offset
Related show

Commit Message

Jonathan Wakely via Gcc-patches July 17, 2020, 2:46 a.m.
Hi all,

This patch adds support for dynamic shadow offset in ASan stack
instrumentation. It is required by Kernel Address Sanitizer in cases where
the shadow offset address is not known at compile-time as the shadow buffer
may not be allocated during the early boot stages.

I used a callback function __asan_shadow_offset() to allow GCC to determine
the shadow offset at runtime. This option is intended to be triggered by
-fsanitize=kernel-address and can be enabled using --param
asan-use-shadow-offset-callback=1.

I've been working on adding ASan feature to coreboot which is a free
software project aimed at replacing the proprietary BIOS (firmware) found
in most computers. We had a requirement for the dynamic shadow offset
option, so we came up with a GCC patch. You can have a look at the change
at https://review.coreboot.org/c/coreboot/+/42794/13.

I know many people have expressed a desire for dynamic shadow offset in GCC
and this feature is already available in Clang, enabled using -mllvm
-asan-force-dynamic-shadow=true flag. So, I thought it would be a useful
feature to have in the upcoming GCC version.


Thanks,
Harshit

--------------------------------------------------------------------------

Add support for using a callback function to fetch shadow offset address
instead of the fixed value defined at compile-time. This feature is enabled
by setting --param asan-use-shadow-offset-callback=1.

2020-07-16    Harshit Sharma    <harshitsharmajs@gmail.com>

gcc/
* asan.c: Use callback function instead of static shadow offset
* params.opt: Define new parameter

---
 gcc/asan.c     | 29 ++++++++++++++++++++++-------
 gcc/params.opt |  4 ++++
 2 files changed, 26 insertions(+), 7 deletions(-)

+
 -param=asan-memintrin=
 Common Joined UInteger Var(param_asan_memintrin) Init(1) IntegerRange(0,
1) Param Optimization
 Enable asan builtin functions protection.
-- 
2.17.1

Patch

diff --git a/gcc/asan.c b/gcc/asan.c
index 9c9aa4cae35..4870f0a0947 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1525,13 +1525,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 (param_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.opt b/gcc/params.opt
index e29a44e7712..5fcf9e7f432 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -50,6 +50,10 @@  Enable asan store operations protection.
 Common Joined UInteger Var(param_asan_instrumentation_with_call_threshold)
Init(7000) Param Optimization
 Use callbacks instead of inline code if number of accesses in function
becomes greater or equal to this number.

+-param=asan-use-shadow-offset-callback=
+Common Joined UInteger Var(param_asan_use_shadow_offset_callback) Init(0)
Param Optimization
+Use shadow offset callback function at runtime instead of fixed value at
compile time at the cost of runtime overhead.