public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Marat Zakirov <m.zakirov@samsung.com>
To: Andrew Pinski <pinskia@gmail.com>
Cc: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>,
	Kostya Serebryany <kcc@google.com>,
	Dmitry Vyukov <dvyukov@google.com>,
	Yury Gribov <y.gribov@samsung.com>,
	Andrey Ryabinin <a.ryabinin@samsung.com>
Subject: [PINGv2][PATCH] ASan on unaligned accesses
Date: Thu, 19 Mar 2015 06:01:00 -0000	[thread overview]
Message-ID: <550A662E.3080308@samsung.com> (raw)
In-Reply-To: <CA+=Sn1k0yOKBr2Z1-S04VSsm097=hEzfMPJgZEgOsf7t4oj=+w@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1027 bytes --]


On 03/04/2015 11:07 AM, Andrew Pinski wrote:
> On Wed, Mar 4, 2015 at 12:00 AM, Marat Zakirov <m.zakirov@samsung.com> wrote:
>> Hi all!
>>
>> Here is the patch which forces ASan to work on memory access without proper
>> alignment. it's useful because some programs like linux kernel often cheat
>> with alignment which may cause false negatives. This patch needs additional
>> support for proper work on unaligned accesses in global data and heap. It
>> will be implemented in libsanitizer by separate patch.
>>
>>
>> --Marat
>>
>> gcc/ChangeLog:
>>
>> 2015-02-25  Marat Zakirov  <m.zakirov@samsung.com>
>>
>>          * asan.c (asan_emit_stack_protection): Support for misalign
>> accesses.
>>          (asan_expand_check_ifn): Likewise.
>>          * params.def: New option asan-catch-misaligned.
>>          * params.h: New param ASAN_CATCH_MISALIGNED.
> Since this parameter can only be true or false, I think it should be a
> normal option.  Also you did not add documentation of the param.
>
> Thanks,
> Andrew
Fixed.


[-- Attachment #2: mavdt-95_17.diff --]
[-- Type: text/x-patch, Size: 8531 bytes --]

gcc/ChangeLog:

2015-03-12  Marat Zakirov  <m.zakirov@samsung.com>

	* asan.c (asan_emit_stack_protection): Support for misalign accesses.
	(asan_expand_check_ifn): Likewise.
	* common.opt: New flag -fasan-catch-misaligned.
	* doc/invoke.texi: New flag description.
	* opts.c (finish_options): Add check for new flag.
	(common_handle_option): Switch on flag if SANITIZE_KERNEL_ADDRESS.

gcc/testsuite/ChangeLog:

2015-03-12  Marat Zakirov  <m.zakirov@samsung.com>

	* c-c++-common/asan/misalign-catch.c: New test.


diff --git a/gcc/asan.c b/gcc/asan.c
index 9e4a629..80bf2e8 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -1050,7 +1050,6 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
   rtx_code_label *lab;
   rtx_insn *insns;
   char buf[30];
-  unsigned char shadow_bytes[4];
   HOST_WIDE_INT base_offset = offsets[length - 1];
   HOST_WIDE_INT base_align_bias = 0, offset, prev_offset;
   HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset;
@@ -1193,11 +1192,37 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
   if (STRICT_ALIGNMENT)
     set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
   prev_offset = base_offset;
+
+  vec<rtx> shadow_mems;
+  vec<unsigned char> shadow_bytes;
+
+  shadow_mems.create(0);
+  shadow_bytes.create(0);
+
   for (l = length; l; l -= 2)
     {
       if (l == 2)
 	cur_shadow_byte = ASAN_STACK_MAGIC_RIGHT;
       offset = offsets[l - 1];
+      if (l != length && flag_asan_catch_misaligned)
+	{
+	  HOST_WIDE_INT aoff
+	    = base_offset + ((offset - base_offset)
+			     & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
+	      - ASAN_RED_ZONE_SIZE;
+	  if (aoff > prev_offset)
+	    {
+	      shadow_mem = adjust_address (shadow_mem, VOIDmode,
+					   (aoff - prev_offset)
+					   >> ASAN_SHADOW_SHIFT);
+	      prev_offset = aoff;
+	      shadow_bytes.safe_push (0);
+	      shadow_bytes.safe_push (0);
+	      shadow_bytes.safe_push (0);
+	      shadow_bytes.safe_push (0);
+	      shadow_mems.safe_push (shadow_mem);
+	    }
+	}
       if ((offset - base_offset) & (ASAN_RED_ZONE_SIZE - 1))
 	{
 	  int i;
@@ -1212,13 +1237,13 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
 	    if (aoff < offset)
 	      {
 		if (aoff < offset - (1 << ASAN_SHADOW_SHIFT) + 1)
-		  shadow_bytes[i] = 0;
+		  shadow_bytes.safe_push (0);
 		else
-		  shadow_bytes[i] = offset - aoff;
+		  shadow_bytes.safe_push (offset - aoff);
 	      }
 	    else
-	      shadow_bytes[i] = ASAN_STACK_MAGIC_PARTIAL;
-	  emit_move_insn (shadow_mem, asan_shadow_cst (shadow_bytes));
+	      shadow_bytes.safe_push (ASAN_STACK_MAGIC_PARTIAL);
+	  shadow_mems.safe_push(shadow_mem);
 	  offset = aoff;
 	}
       while (offset <= offsets[l - 2] - ASAN_RED_ZONE_SIZE)
@@ -1227,12 +1252,21 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
 				       (offset - prev_offset)
 				       >> ASAN_SHADOW_SHIFT);
 	  prev_offset = offset;
-	  memset (shadow_bytes, cur_shadow_byte, 4);
-	  emit_move_insn (shadow_mem, asan_shadow_cst (shadow_bytes));
+	  shadow_bytes.safe_push (cur_shadow_byte);
+	  shadow_bytes.safe_push (cur_shadow_byte);
+	  shadow_bytes.safe_push (cur_shadow_byte);
+	  shadow_bytes.safe_push (cur_shadow_byte);
+	  shadow_mems.safe_push(shadow_mem);
 	  offset += ASAN_RED_ZONE_SIZE;
 	}
       cur_shadow_byte = ASAN_STACK_MAGIC_MIDDLE;
     }
+  for (unsigned i = 0; flag_asan_catch_misaligned && i < shadow_bytes.length () - 1; i++)
+    if (shadow_bytes[i] == 0 && shadow_bytes[i + 1] > 0)
+      shadow_bytes[i] = 8 + (shadow_bytes[i + 1] > 7 ? 0 : shadow_bytes[i + 1]);
+  for (unsigned i = 0; i < shadow_mems.length (); i++)
+    emit_move_insn (shadow_mems[i], asan_shadow_cst (&shadow_bytes[i * 4]));
+  
   do_pending_stack_adjust ();
 
   /* Construct epilogue sequence.  */
@@ -1285,34 +1319,8 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
   if (STRICT_ALIGNMENT)
     set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
 
-  prev_offset = base_offset;
-  last_offset = base_offset;
-  last_size = 0;
-  for (l = length; l; l -= 2)
-    {
-      offset = base_offset + ((offsets[l - 1] - base_offset)
-			     & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
-      if (last_offset + last_size != offset)
-	{
-	  shadow_mem = adjust_address (shadow_mem, VOIDmode,
-				       (last_offset - prev_offset)
-				       >> ASAN_SHADOW_SHIFT);
-	  prev_offset = last_offset;
-	  asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
-	  last_offset = offset;
-	  last_size = 0;
-	}
-      last_size += base_offset + ((offsets[l - 2] - base_offset)
-				  & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
-		   - offset;
-    }
-  if (last_size)
-    {
-      shadow_mem = adjust_address (shadow_mem, VOIDmode,
-				   (last_offset - prev_offset)
-				   >> ASAN_SHADOW_SHIFT);
-      asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
-    }
+  for (unsigned i = 0; i < shadow_mems.length (); i++)
+    asan_clear_shadow (shadow_mems[i], 4);
 
   do_pending_stack_adjust ();
   if (lab)
@@ -2643,7 +2651,7 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
   tree base_addr = gimple_assign_lhs (g);
 
   tree t = NULL_TREE;
-  if (real_size_in_bytes >= 8)
+  if (real_size_in_bytes >= 8 && !flag_asan_catch_misaligned)
     {
       tree shadow = build_shadow_mem_access (&gsi, loc, base_addr,
 					     shadow_ptr_type);
@@ -2662,7 +2670,7 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls)
       /* Aligned (>= 8 bytes) can test just
 	 (real_size_in_bytes - 1 >= shadow), as base_addr & 7 is known
 	 to be 0.  */
-      if (align < 8)
+      if (align < 8 || flag_asan_catch_misaligned)
 	{
 	  gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR,
 						   base_addr, 7));
diff --git a/gcc/common.opt b/gcc/common.opt
index b49ac46..a7af95e 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1161,6 +1161,12 @@ Common Driver Var(flag_report_bug)
 Collect and dump debug information into temporary file if ICE in C/C++
 compiler occured.
 
+fasan-catch-misaligned
+Common Driver Var(flag_asan_catch_misaligned)
+Catch invalid unaligned memory accesses.
+This option is needed to prevent potential ASan false positives due to 
+unaligned to type size memory accesses in some apllication like Linux kernel.
+
 fdump-passes
 Common Var(flag_dump_passes) Init(0)
 Dump optimization passes
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 1534ed9..c85aa38 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -6680,6 +6680,12 @@ text / bss / data / heap / stack / dso start locations.
 Collect and dump debug information into temporary file if ICE in C/C++
 compiler occured.
 
+@item -fasan-catch-misaligned
+@opindex fasan-catch-misaligned
+Catch invalid unaligned memory accesses.
+This option is needed to prevent potential ASan false positives due to 
+unaligned to type size memory accesses in some apllication like Linux kernel.
+
 @item -fdump-unnumbered
 @opindex fdump-unnumbered
 When doing debugging dumps, suppress instruction numbers and address output.
diff --git a/gcc/opts.c b/gcc/opts.c
index 39c190d..b238b90 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -925,6 +925,9 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
       opts->x_flag_aggressive_loop_optimizations = 0;
       opts->x_flag_strict_overflow = 0;
     }
+  
+  if (flag_asan_catch_misaligned && !opts->x_flag_sanitize)
+    error_at (loc, "-fasan-catch-misaligned is valid only with -fsanitize option");
 }
 
 #define LEFT_COLUMN	27
@@ -1662,6 +1665,7 @@ common_handle_option (struct gcc_options *opts,
 	    maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0,
 				   opts->x_param_values,
 				   opts_set->x_param_values);
+            flag_asan_catch_misaligned = true;
 	  }
 
 	break;
diff --git a/gcc/testsuite/c-c++-common/asan/misalign-catch.c b/gcc/testsuite/c-c++-common/asan/misalign-catch.c
new file mode 100644
index 0000000..158efd4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/misalign-catch.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-fasan-catch-misaligned" } */
+/* { dg-shouldfail "asan" } */
+
+long long *ptr;
+
+__attribute__((noinline))
+void foo () {
+   ptr = ((long long int *)(((char *)ptr) + 1));
+   *ptr = 1;
+}
+
+int main()
+{
+   long long int local[9];
+   ptr = (long long *)&local[8];
+   foo ();
+   return 0;
+}
+
+/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow.*(\n|\r\n|\r)" } */

  reply	other threads:[~2015-03-19  6:01 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-04  8:00 [PATCH] " Marat Zakirov
2015-03-04  8:07 ` Andrew Pinski
2015-03-19  6:01   ` Marat Zakirov [this message]
2015-03-26  6:53     ` [PINGv3][PATCH] " Marat Zakirov
2015-03-26 11:50       ` Jakub Jelinek
2015-03-26 12:29         ` [PINGv4][PATCH] " Marat Zakirov
2015-03-30 17:43           ` Jakub Jelinek
2015-04-07 10:16             ` [PINGv5][PATCH] " Marat Zakirov
2015-04-07 12:22               ` Jakub Jelinek
2015-05-12 11:23                 ` [PINGv6][PATCH] " Marat Zakirov
2015-05-12 11:45                   ` Yury Gribov
2015-05-20  7:19                   ` [PINGv7][PATCH] " Marat Zakirov
2015-05-26 14:12                     ` [PINGv8][PATCH] " Marat Zakirov
2015-06-02 13:15                       ` [PINGv9][PATCH] " Marat Zakirov
2015-06-11 11:04                         ` [PINGv10][PATCH] " Marat Zakirov
2015-03-12 12:07 ` [PING][PATCH] " Marat Zakirov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=550A662E.3080308@samsung.com \
    --to=m.zakirov@samsung.com \
    --cc=a.ryabinin@samsung.com \
    --cc=dvyukov@google.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=kcc@google.com \
    --cc=pinskia@gmail.com \
    --cc=y.gribov@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).