diff mbox

[PATCHv4,Kasan] Allow to override Asan shadow offset from command line

Message ID 5440CADD.6060100@samsung.com
State New
Headers show

Commit Message

Yury Gribov Oct. 17, 2014, 7:53 a.m. UTC
Hi all,

On 09/29/2014 09:21 PM, Yury Gribov wrote:
>>> 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.

New patchset that adds strtoull to libiberty (blind copy-paste of 
already existing strtoul.c) and uses it to parse -fasan-shadow-offset 
(to avoid problem with compiling for 64-bit target a 32-bit host).

Bootstrapped and regtested on x64.

-Y

Comments

Jakub Jelinek Oct. 17, 2014, 11:05 a.m. UTC | #1
On Fri, Oct 17, 2014 at 11:53:01AM +0400, Yury Gribov wrote:
> >From 0225b7878bbb5b803814646d089824d016316fef Mon Sep 17 00:00:00 2001
> From: Yury Gribov <y.gribov@samsung.com>
> Date: Thu, 16 Oct 2014 18:31:10 +0400
> Subject: [PATCH 1/2] Add strtoull to libiberty.
> 
> 2014-10-17  Yury Gribov  <y.gribov@samsung.com>
> 
> libiberty/
> 	* strtoull.c: New file.

Just putting a file in there won't magically make it be part of libiberty.
Please read libiberty/README on how to add an optional file.
strtoul is also optional as strotoull should be, so you can also just
grep for strtoul in libiberty/* and add on similar spots.

Not sure if there aren't extra steps to make strtoull prototype available
in system.h, libiberty.h etc. for systems that don't have strtoull in their
headers.

CCing Ian as libiberty maintainer.

	Jakub
Ian Lance Taylor Oct. 17, 2014, 12:32 p.m. UTC | #2
Jakub Jelinek <jakub@redhat.com> writes:

> Not sure if there aren't extra steps to make strtoull prototype available
> in system.h, libiberty.h etc. for systems that don't have strtoull in their
> headers.

See the

#if defined(HAVE_DECL_XXX) && !HAVE_DECL_XXX

lines in include/libiberty.h.  Although strtol is missing there as well.

Ian
diff mbox

Patch

From 6c9ad20bdcfc0fbf7ccb8e2700ef7dce52a34c64 Mon Sep 17 00:00:00 2001
From: Yury Gribov <y.gribov@samsung.com>
Date: Fri, 29 Aug 2014 11:58:03 +0400
Subject: [PATCH 2/2] Allow to override Asan shadow offset.

2014-10-17  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.
---
 gcc/asan.c                                        |   43 +++++++++++++++++++--
 gcc/asan.h                                        |    4 +-
 gcc/common.opt                                    |    4 ++
 gcc/doc/invoke.texi                               |    8 +++-
 gcc/opts-global.c                                 |    9 +++++
 gcc/opts.c                                        |    4 ++
 gcc/testsuite/c-c++-common/asan/shadow-offset-1.c |   11 ++++++
 7 files changed, 78 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/asan/shadow-offset-1.c

diff --git a/gcc/asan.c b/gcc/asan.c
index 2a61a82..8bd4db9 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -238,6 +238,43 @@  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;
+#ifdef HAVE_LONG_LONG
+  asan_shadow_offset_value = strtoull (val, &endp, 0);
+#else
+  asan_shadow_offset_value = strtoul (val, &endp, 0);
+#endif
+  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 +1161,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);
@@ -1503,7 +1540,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,
@@ -1520,7 +1557,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 5db5e1e..5492d0d 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 6bc09d6..3b53dfa 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
@@ -5629,6 +5629,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 dc8ddf4..89d4f0e 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1584,6 +1584,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" } } */
-- 
1.7.9.5