This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCHv3][Kasan][PING] Allow to override Asan shadow offset from command line


Hi all,

Kasan developers has asked for an option to override offset of Asan
shadow memory region. This should simplify experimenting with memory
layouts on 64-bit architectures.

New patch which checks that -fasan-shadow-offset is only enabled for -fsanitize=kernel-address. I (unfortunately) can't make this --param because this can be a 64-bit value.

Bootstrapped and regtested on x64.

-Y
commit 05829f7922915b075c0f4275d3613947aa793a9c
Author: Yury Gribov <y.gribov@samsung.com>
Date:   Fri Aug 29 11:58:03 2014 +0400

    Allow to override Asan shadow offset.
    
    2014-09-26  Yury Gribov  <y.gribov@samsung.com>
    
    gcc/
    	* asan.c (set_asan_shadow_offset): New function.
    	(asan_shadow_offset): Likewise.
    	(asan_emit_stack_protection): Call asan_shadow_offset.
    	(build_shadow_mem_access): Likewise.
    	* asan.h (set_asan_shadow_offset): Declare.
    	* common.opt (fasan-shadow-offset): New option.
    	* doc/invoke.texi (fasan-shadow-offset): Describe new option.
    	* opts-global.c (handle_common_deferred_options): Handle
    	-fasan-shadow-offset.
    	* opts.c (common_handle_option): Likewise.
    
    gcc/testsuite/
    	* c-c++-common/asan/shadow-offset-1.c: New test.

diff --git a/gcc/asan.c b/gcc/asan.c
index f520eab..63f99f5 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -238,6 +238,39 @@ along with GCC; see the file COPYING3.  If not see
    A destructor function that calls the runtime asan library function
    _asan_unregister_globals is also installed.  */
 
+static unsigned HOST_WIDE_INT asan_shadow_offset_value;
+static bool asan_shadow_offset_computed;
+
+/* Sets shadow offset to value in string VAL.  */
+
+bool
+set_asan_shadow_offset (const char *val)
+{
+  char *endp;
+  
+  errno = 0;
+  asan_shadow_offset_value = strtoul (val, &endp, 0);
+  if (!(*val != '\0' && *endp == '\0' && errno == 0))
+    return false;
+
+  asan_shadow_offset_computed = true;
+
+  return true;
+}
+
+/* Returns Asan shadow offset.  */
+
+static unsigned HOST_WIDE_INT
+asan_shadow_offset ()
+{
+  if (!asan_shadow_offset_computed)
+    {
+      asan_shadow_offset_computed = true;
+      asan_shadow_offset_value = targetm.asan_shadow_offset ();
+    }
+  return asan_shadow_offset_value;
+}
+
 alias_set_type asan_shadow_set = -1;
 
 /* Pointer types to 1 resp. 2 byte integers in shadow memory.  A separate
@@ -1124,7 +1157,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
 			      NULL_RTX, 1, OPTAB_DIRECT);
   shadow_base
     = plus_constant (Pmode, shadow_base,
-		     targetm.asan_shadow_offset ()
+		     asan_shadow_offset ()
 		     + (base_align_bias >> ASAN_SHADOW_SHIFT));
   gcc_assert (asan_shadow_set != -1
 	      && (ASAN_RED_ZONE_SIZE >> ASAN_SHADOW_SHIFT) == 4);
@@ -1502,7 +1535,7 @@ insert_if_then_before_iter (gimple cond,
 }
 
 /* Build
-   (base_addr >> ASAN_SHADOW_SHIFT) + targetm.asan_shadow_offset ().  */
+   (base_addr >> ASAN_SHADOW_SHIFT) + asan_shadow_offset ().  */
 
 static tree
 build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location,
@@ -1519,7 +1552,7 @@ build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location,
   gimple_set_location (g, location);
   gsi_insert_after (gsi, g, GSI_NEW_STMT);
 
-  t = build_int_cst (uintptr_type, targetm.asan_shadow_offset ());
+  t = build_int_cst (uintptr_type, asan_shadow_offset ());
   g = gimple_build_assign_with_ops (PLUS_EXPR,
 				    make_ssa_name (uintptr_type, NULL),
 				    gimple_assign_lhs (g), t);
diff --git a/gcc/asan.h b/gcc/asan.h
index 198433f..eadf029 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -36,7 +36,7 @@ extern gimple_stmt_iterator create_cond_insert_point
 extern alias_set_type asan_shadow_set;
 
 /* Shadow memory is found at
-   (address >> ASAN_SHADOW_SHIFT) + targetm.asan_shadow_offset ().  */
+   (address >> ASAN_SHADOW_SHIFT) + asan_shadow_offset ().  */
 #define ASAN_SHADOW_SHIFT	3
 
 /* Red zone size, stack and global variables are padded by ASAN_RED_ZONE_SIZE
@@ -76,4 +76,6 @@ asan_red_zone_size (unsigned int size)
   return c ? 2 * ASAN_RED_ZONE_SIZE - c : ASAN_RED_ZONE_SIZE;
 }
 
+extern bool set_asan_shadow_offset (const char *);
+
 #endif /* TREE_ASAN */
diff --git a/gcc/common.opt b/gcc/common.opt
index b4f0ed4..90f6bd4 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -879,6 +879,10 @@ fsanitize=
 Common Driver Report Joined
 Select what to sanitize
 
+fasan-shadow-offset=
+Common Joined RejectNegative Var(common_deferred_options) Defer
+-fasan-shadow-offset=<string>	Use custom shadow memory offset.
+
 fsanitize-recover
 Common Report Var(flag_sanitize_recover) Init(1)
 After diagnosing undefined behavior attempt to continue execution
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index f6c3b42..d9bd1f7 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -297,7 +297,7 @@ Objective-C and Objective-C++ Dialects}.
 @xref{Debugging Options,,Options for Debugging Your Program or GCC}.
 @gccoptlist{-d@var{letters}  -dumpspecs  -dumpmachine  -dumpversion @gol
 -fsanitize=@var{style} -fsanitize-recover @gol
--fsanitize-undefined-trap-on-error @gol
+-fasan-shadow-offset=@var{string} -fsanitize-undefined-trap-on-error @gol
 -fdbg-cnt-list -fdbg-cnt=@var{counter-value-list} @gol
 -fdisable-ipa-@var{pass_name} @gol
 -fdisable-rtl-@var{pass_name} @gol
@@ -5610,6 +5610,12 @@ While @option{-ftrapv} causes traps for signed overflows to be emitted,
 @option{-fsanitize=undefined} gives a diagnostic message.
 This currently works only for the C family of languages.
 
+@item -fasan-shadow-offset=@var{string}
+@opindex fasan-shadow-offset
+This option forces GCC to use custom shadow offset in AddressSanitizer checks.
+It is useful for experimenting with different shadow memory layouts in
+kernel AddressSanitizer.
+
 @item -fsanitize-recover
 @opindex fsanitize-recover
 By default @option{-fsanitize=undefined} sanitization (and its suboptions
diff --git a/gcc/opts-global.c b/gcc/opts-global.c
index 111884b..81c899c 100644
--- a/gcc/opts-global.c
+++ b/gcc/opts-global.c
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "toplev.h"
 #include "tree-pass.h"
 #include "context.h"
+#include "asan.h"
 
 typedef const char *const_char_p; /* For DEF_VEC_P.  */
 
@@ -426,6 +427,14 @@ handle_common_deferred_options (void)
 	  stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (opt->arg));
 	  break;
 
+	case OPT_fasan_shadow_offset_:
+	  if (!(flag_sanitize & SANITIZE_KERNEL_ADDRESS))
+	    error ("-fasan-shadow-offset should only be used "
+		   "with -fsanitize=kernel-address");
+	  if (!set_asan_shadow_offset (opt->arg))
+	     error ("unrecognized shadow offset %qs", opt->arg);
+	  break;
+
 	default:
 	  gcc_unreachable ();
 	}
diff --git a/gcc/opts.c b/gcc/opts.c
index 0a49bc0..774a599 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1572,6 +1572,10 @@ common_handle_option (struct gcc_options *opts,
 	break;
       }
 
+    case OPT_fasan_shadow_offset_:
+      /* Deferred.  */
+      break;
+
     case OPT_O:
     case OPT_Os:
     case OPT_Ofast:
diff --git a/gcc/testsuite/c-c++-common/asan/shadow-offset-1.c b/gcc/testsuite/c-c++-common/asan/shadow-offset-1.c
new file mode 100644
index 0000000..2ca0fd6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/shadow-offset-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address --param asan-instrumentation-with-call-threshold=100 -fasan-shadow-offset=12345 -fdump-tree-sanopt" } */
+/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */
+ 
+int f (int *p)
+{
+  return *p;
+}
+
+/* { dg-final { scan-tree-dump "12345" "sanopt" }  } */
+/* { dg-final { cleanup-tree-dump "sanopt" } } */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]