diff mbox

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

Message ID 544A5A95.6030502@samsung.com
State New
Headers show

Commit Message

Yury Gribov Oct. 24, 2014, 1:56 p.m. UTC
Hi all,

On 10/17/2014 11:53 AM, Yury Gribov wrote:
> 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.
>
> 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).

A new version of patchset which does a proper implementation of 
strtoll/strtoull in libiberty (with tests, docs and stuff).

Bootstrapped and regtested on x64.

As mentioned previously, I'm not sure how to properly test strtoll 
implementation (strtoll is already part of Linux glibc so my 
implementation is not compiled in by default).  I've manually embedded 
strtoll.o/strtoull.o into libiberty.a and verified that regression tests 
passed.

-Y

Comments

Jakub Jelinek Oct. 24, 2014, 2:02 p.m. UTC | #1
On Fri, Oct 24, 2014 at 05:56:37PM +0400, Yury Gribov wrote:
> >From 1882c41de6c8ae53b7e199b3cc655b6f4b31e8fb 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 strtoll and strtoull to libiberty.
> 
> 2014-10-20  Yury Gribov  <y.gribov@samsung.com>
> 
> include/
> 	* libiberty.h (strtol, strtoul, strtoll, strtoull): New prototypes.
> 
> libiberty/
> 	* strtoll.c: New file.
> 	* strtoull.c: New file.
> 	* configure.ac: Add long long checks. Add harness for strtoll and
> 	strtoull. Check decls for strtol, strtoul, strtoll, strtoull.
> 	* Makefile.in (CFILES, CONFIGURED_OFILES): Added strtoll and strtoull.
> 	* config.in: Regenerate.
> 	* configure: Regenerate.
> 	* functions.texi: Regenerate.
> 	* testsuite/Makefile.in (check-strtol): New rule.
> 	(test-strtol): Likewise.
> 	(mostlyclean): Clean up strtol test.
> 	* testsuite/test-strtol.c: New test.

Ian, can you please review this?

> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -883,6 +883,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.

Shouldn't that be =<number> or =<address> instead of string?

> --- 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 -fsanitize-recover=@var{style} @gol
> --fsanitize-undefined-trap-on-error @gol
> +-fasan-shadow-offset=@var{string} -fsanitize-undefined-trap-on-error @gol

Likewise here, @var{number} instead.

>  -fdbg-cnt-list -fdbg-cnt=@var{counter-value-list} @gol
>  -fdisable-ipa-@var{pass_name} @gol
>  -fdisable-rtl-@var{pass_name} @gol
> @@ -5642,6 +5642,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}

And here.

Otherwise looks good to me.

	Jakub
Ian Lance Taylor Oct. 27, 2014, 3:58 p.m. UTC | #2
Yury Gribov <y.gribov@samsung.com> writes:

> --- a/include/libiberty.h
> +++ b/include/libiberty.h
> @@ -655,6 +655,33 @@ extern size_t strnlen (const char *, size_t);
>  extern int strverscmp (const char *, const char *);
>  #endif
>  
> +#if defined(HAVE_DECL_STRTOL) && !HAVE_DECL_STRTOL
> +extern long int strtol (const char *nptr,
> +                        char **endptr, int base);
> +#endif
> +
> +#if defined(HAVE_DECL_STRTOUL) && !HAVE_DECL_STRTOUL
> +extern unsigned long int strtoul (const char *nptr,
> +                                  char **endptr, int base);
> +#endif
> +
> +#if defined(HAVE_DECL_STRTOLL) && !HAVE_DECL_STRTOLL
> +__extension__
> +extern long long int strtoll (const char *nptr,
> +                              char **endptr, int base);
> +#endif
> +
> +#if defined(HAVE_DECL_STRTOULL) && !HAVE_DECL_STRTOULL
> +__extension__
> +extern unsigned long long int strtoull (const char *nptr,
> +                                        char **endptr, int base);
> +#endif


Your patch is otherwise careful to check that only use "long long" if
the compiler supports it.  Here you are not.  I think you need to wrap
the declarations of strtoll and strtoull in

#ifdef HAVE_LONG_LONG

With that change the libiberty/include patch is OK.

Thanks.

Ian
diff mbox

Patch

From f5a6525be7b7e37ce1c34ca538001fc2b8e6194e 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 97f0b4c..b4ef022 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 da5250b..ac4e48e 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -883,6 +883,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 Joined
 After diagnosing undefined behavior attempt to continue execution
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c9ca404..a9e4b9c 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 -fsanitize-recover=@var{style} @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
@@ -5642,6 +5642,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@r{[}=@var{opts}@r{]}
 @opindex fsanitize-recover
 @opindex fno-sanitize-recover
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 25f5235..db30b65 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -1646,6 +1646,10 @@  common_handle_option (struct gcc_options *opts,
 	break;
       }
 
+    case OPT_fasan_shadow_offset_:
+      /* Deferred.  */
+      break;
+
     case OPT_fsanitize_recover:
       if (value)
 	opts->x_flag_sanitize_recover
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