public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH PR64820] Fix ASan UAR detection fails on 32-bit targets if SSP is enabled.
@ 2015-02-09 11:04 Maxim Ostapenko
  2015-02-16  7:58 ` [Ping] " Maxim Ostapenko
  2015-03-15 20:23 ` Richard Sandiford
  0 siblings, 2 replies; 6+ messages in thread
From: Maxim Ostapenko @ 2015-02-09 11:04 UTC (permalink / raw)
  To: GCC Patches; +Cc: Yury Gribov, Slava Garbuzov

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

Hi,

when testing I noticed, that if compile with both -fsanitize=address and 
-fstack-protector for 32-bit architectures and run with 
ASAN_OPTIONS=detect_stack_use_after_return=1, libsanitizer fails with:

  ==7299==AddressSanitizer CHECK failed: 
/home/max/workspace/downloads/gcc/libsanitizer/asan/asan_poisoning.cc:25 
"((AddrIsAlignedByGranularity(addr + size))) != (0)" (0x0, 0x0)
     #0 0xf72d8afc in AsanCheckFailed 
/home/max/workspace/downloads/gcc/libsanitizer/asan/asan_rtl.cc:68
     #1 0xf72dda89 in __sanitizer::CheckFailed(char const*, int, char 
const*, unsigned long long, unsigned long long) 
/home/max/workspace/downloads/gcc/libsanitizer/sanitizer_common/sanitizer_common.cc:72

This happens because ssp inserts a stack guard into a function, that 
confuses asan_emit_stack_protection to calculate right size parameter 
for asan_stack_malloc.

This tiny patch resolves the issue.

Regtested with make -j12 -k check 
RUNTESTFLAGS='--target_board=unix\{-m32,-m64\}' on x86_64-unknown-linux-gnu.

Bootstrapped, ASan-bootstrapped on x86_64-unknown-linux-gnu.

Ok to commit?

-Maxim



[-- Attachment #2: ssp_asan-6.diff --]
[-- Type: text/x-patch, Size: 3679 bytes --]

gcc/ChangeLog:

2015-02-09  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	PR sanitizer/64820
        * cfgexpand.c (align_base): New function.
        (alloc_stack_frame_space): Call it.
        (expand_stack_vars): Align prev_frame to be sure
        data->asan_vec elements aligned properly.

gcc/testsuite/ChangeLog:

2015-02-09  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	PR sanitizer/64820
        * c-c++-common/asan/pr64820.c: New test.

diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 7dfe1f6..7845a17 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -282,6 +282,15 @@ align_local_variable (tree decl)
   return align / BITS_PER_UNIT;
 }
 
+/* Align given offset BASE with ALIGN.  Truncate up if ALIGN_UP is true,
+   down otherwise.  Return truncated BASE value.  */
+
+static inline unsigned HOST_WIDE_INT
+align_base (HOST_WIDE_INT base, unsigned HOST_WIDE_INT align, bool align_up)
+{
+  return align_up ? (base + align - 1) & -align : base & -align;
+}
+
 /* Allocate SIZE bytes at byte alignment ALIGN from the stack frame.
    Return the frame offset.  */
 
@@ -293,17 +302,15 @@ alloc_stack_frame_space (HOST_WIDE_INT size, unsigned HOST_WIDE_INT align)
   new_frame_offset = frame_offset;
   if (FRAME_GROWS_DOWNWARD)
     {
-      new_frame_offset -= size + frame_phase;
-      new_frame_offset &= -align;
-      new_frame_offset += frame_phase;
+      new_frame_offset
+	= align_base (frame_offset - frame_phase - size,
+		      align, false) + frame_phase;
       offset = new_frame_offset;
     }
   else
     {
-      new_frame_offset -= frame_phase;
-      new_frame_offset += align - 1;
-      new_frame_offset &= -align;
-      new_frame_offset += frame_phase;
+      new_frame_offset
+	= align_base (frame_offset - frame_phase, align, true) + frame_phase;
       offset = new_frame_offset;
       new_frame_offset += size;
     }
@@ -1031,13 +1038,16 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
 	  base = virtual_stack_vars_rtx;
 	  if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && pred)
 	    {
-	      HOST_WIDE_INT prev_offset = frame_offset;
+	      HOST_WIDE_INT prev_offset
+		= align_base (frame_offset,
+			      MAX (alignb, ASAN_RED_ZONE_SIZE),
+			      FRAME_GROWS_DOWNWARD);
 	      tree repr_decl = NULL_TREE;
-
 	      offset
 		= alloc_stack_frame_space (stack_vars[i].size
 					   + ASAN_RED_ZONE_SIZE,
 					   MAX (alignb, ASAN_RED_ZONE_SIZE));
+
 	      data->asan_vec.safe_push (prev_offset);
 	      data->asan_vec.safe_push (offset + stack_vars[i].size);
 	      /* Find best representative of the partition.
diff --git a/gcc/testsuite/c-c++-common/asan/pr64820.c b/gcc/testsuite/c-c++-common/asan/pr64820.c
new file mode 100644
index 0000000..885a662
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr64820.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fstack_protector } */
+/* { dg-options "-fstack-protector-strong" } */
+/* { dg-set-target-env-var ASAN_OPTIONS "detect_stack_use_after_return=1" } */
+/* { dg-shouldfail "asan" } */
+
+__attribute__((noinline))
+char *Ident(char *x) {
+  return x;
+}
+
+__attribute__((noinline))
+char *Func1() {
+  char local[1 << 12];
+  return Ident(local);
+}
+
+__attribute__((noinline))
+void Func2(char *x) {
+  *x = 1;
+}
+int main(int argc, char **argv) {
+  Func2(Func1());
+  return 0;
+}
+
+/* { dg-output "AddressSanitizer: stack-use-after-return on address 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "WRITE of size 1 at .* thread T0.*" } */
+/* { dg-output "    #0.*(Func2)?.*pr64820.(c:21)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Ping] [PATCH PR64820] Fix ASan UAR detection fails on 32-bit targets if SSP is enabled.
  2015-02-09 11:04 [PATCH PR64820] Fix ASan UAR detection fails on 32-bit targets if SSP is enabled Maxim Ostapenko
@ 2015-02-16  7:58 ` Maxim Ostapenko
  2015-02-25 14:50   ` [Ping v2] " Maxim Ostapenko
  2015-03-15 20:23 ` Richard Sandiford
  1 sibling, 1 reply; 6+ messages in thread
From: Maxim Ostapenko @ 2015-02-16  7:58 UTC (permalink / raw)
  To: GCC Patches; +Cc: Yury Gribov, Slava Garbuzov

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

Ping.


-------- Original Message --------
Subject: 	[PATCH PR64820] Fix ASan UAR detection fails on 32-bit targets 
if SSP is enabled.
Date: 	Mon, 09 Feb 2015 14:03:54 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov 
<v.garbuzov@samsung.com>



Hi,

when testing I noticed, that if compile with both -fsanitize=address and
-fstack-protector for 32-bit architectures and run with
ASAN_OPTIONS=detect_stack_use_after_return=1, libsanitizer fails with:

   ==7299==AddressSanitizer CHECK failed:
/home/max/workspace/downloads/gcc/libsanitizer/asan/asan_poisoning.cc:25
"((AddrIsAlignedByGranularity(addr + size))) != (0)" (0x0, 0x0)
      #0 0xf72d8afc in AsanCheckFailed
/home/max/workspace/downloads/gcc/libsanitizer/asan/asan_rtl.cc:68
      #1 0xf72dda89 in __sanitizer::CheckFailed(char const*, int, char
const*, unsigned long long, unsigned long long)
/home/max/workspace/downloads/gcc/libsanitizer/sanitizer_common/sanitizer_common.cc:72

This happens because ssp inserts a stack guard into a function, that
confuses asan_emit_stack_protection to calculate right size parameter
for asan_stack_malloc.

This tiny patch resolves the issue.

Regtested with make -j12 -k check
RUNTESTFLAGS='--target_board=unix\{-m32,-m64\}' on x86_64-unknown-linux-gnu.

Bootstrapped, ASan-bootstrapped on x86_64-unknown-linux-gnu.

Ok to commit?

-Maxim






[-- Attachment #2: ssp_asan-6.diff --]
[-- Type: text/x-patch, Size: 3680 bytes --]

gcc/ChangeLog:

2015-02-09  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	PR sanitizer/64820
        * cfgexpand.c (align_base): New function.
        (alloc_stack_frame_space): Call it.
        (expand_stack_vars): Align prev_frame to be sure
        data->asan_vec elements aligned properly.

gcc/testsuite/ChangeLog:

2015-02-09  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	PR sanitizer/64820
        * c-c++-common/asan/pr64820.c: New test.

diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 7dfe1f6..7845a17 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -282,6 +282,15 @@ align_local_variable (tree decl)
   return align / BITS_PER_UNIT;
 }
 
+/* Align given offset BASE with ALIGN.  Truncate up if ALIGN_UP is true,
+   down otherwise.  Return truncated BASE value.  */
+
+static inline unsigned HOST_WIDE_INT
+align_base (HOST_WIDE_INT base, unsigned HOST_WIDE_INT align, bool align_up)
+{
+  return align_up ? (base + align - 1) & -align : base & -align;
+}
+
 /* Allocate SIZE bytes at byte alignment ALIGN from the stack frame.
    Return the frame offset.  */
 
@@ -293,17 +302,15 @@ alloc_stack_frame_space (HOST_WIDE_INT size, unsigned HOST_WIDE_INT align)
   new_frame_offset = frame_offset;
   if (FRAME_GROWS_DOWNWARD)
     {
-      new_frame_offset -= size + frame_phase;
-      new_frame_offset &= -align;
-      new_frame_offset += frame_phase;
+      new_frame_offset
+	= align_base (frame_offset - frame_phase - size,
+		      align, false) + frame_phase;
       offset = new_frame_offset;
     }
   else
     {
-      new_frame_offset -= frame_phase;
-      new_frame_offset += align - 1;
-      new_frame_offset &= -align;
-      new_frame_offset += frame_phase;
+      new_frame_offset
+	= align_base (frame_offset - frame_phase, align, true) + frame_phase;
       offset = new_frame_offset;
       new_frame_offset += size;
     }
@@ -1031,13 +1038,16 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
 	  base = virtual_stack_vars_rtx;
 	  if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && pred)
 	    {
-	      HOST_WIDE_INT prev_offset = frame_offset;
+	      HOST_WIDE_INT prev_offset
+		= align_base (frame_offset,
+			      MAX (alignb, ASAN_RED_ZONE_SIZE),
+			      FRAME_GROWS_DOWNWARD);
 	      tree repr_decl = NULL_TREE;
-
 	      offset
 		= alloc_stack_frame_space (stack_vars[i].size
 					   + ASAN_RED_ZONE_SIZE,
 					   MAX (alignb, ASAN_RED_ZONE_SIZE));
+
 	      data->asan_vec.safe_push (prev_offset);
 	      data->asan_vec.safe_push (offset + stack_vars[i].size);
 	      /* Find best representative of the partition.
diff --git a/gcc/testsuite/c-c++-common/asan/pr64820.c b/gcc/testsuite/c-c++-common/asan/pr64820.c
new file mode 100644
index 0000000..885a662
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr64820.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fstack_protector } */
+/* { dg-options "-fstack-protector-strong" } */
+/* { dg-set-target-env-var ASAN_OPTIONS "detect_stack_use_after_return=1" } */
+/* { dg-shouldfail "asan" } */
+
+__attribute__((noinline))
+char *Ident(char *x) {
+  return x;
+}
+
+__attribute__((noinline))
+char *Func1() {
+  char local[1 << 12];
+  return Ident(local);
+}
+
+__attribute__((noinline))
+void Func2(char *x) {
+  *x = 1;
+}
+int main(int argc, char **argv) {
+  Func2(Func1());
+  return 0;
+}
+
+/* { dg-output "AddressSanitizer: stack-use-after-return on address 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "WRITE of size 1 at .* thread T0.*" } */
+/* { dg-output "    #0.*(Func2)?.*pr64820.(c:21)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Ping v2] [PATCH PR64820] Fix ASan UAR detection fails on 32-bit targets if SSP is enabled.
  2015-02-16  7:58 ` [Ping] " Maxim Ostapenko
@ 2015-02-25 14:50   ` Maxim Ostapenko
  2015-03-03  8:33     ` [Ping v3] " Maxim Ostapenko
  0 siblings, 1 reply; 6+ messages in thread
From: Maxim Ostapenko @ 2015-02-25 14:50 UTC (permalink / raw)
  To: GCC Patches; +Cc: Yury Gribov, Slava Garbuzov

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

On 02/16/2015 10:58 AM, Maxim Ostapenko wrote:
> Hi,
>
> when testing I noticed, that if compile with both -fsanitize=address and
> -fstack-protector for 32-bit architectures and run with
> ASAN_OPTIONS=detect_stack_use_after_return=1, libsanitizer fails with:
>
>   ==7299==AddressSanitizer CHECK failed:
> /home/max/workspace/downloads/gcc/libsanitizer/asan/asan_poisoning.cc:25
> "((AddrIsAlignedByGranularity(addr + size))) != (0)" (0x0, 0x0)
>      #0 0xf72d8afc in AsanCheckFailed
> /home/max/workspace/downloads/gcc/libsanitizer/asan/asan_rtl.cc:68
>      #1 0xf72dda89 in __sanitizer::CheckFailed(char const*, int, char
> const*, unsigned long long, unsigned long long)
> /home/max/workspace/downloads/gcc/libsanitizer/sanitizer_common/sanitizer_common.cc:72 
>
>
> This happens because ssp inserts a stack guard into a function, that
> confuses asan_emit_stack_protection to calculate right size parameter
> for asan_stack_malloc.
>
> This tiny patch resolves the issue.
>
> Regtested with make -j12 -k check
> RUNTESTFLAGS='--target_board=unix\{-m32,-m64\}' on 
> x86_64-unknown-linux-gnu.
>
> Bootstrapped, ASan-bootstrapped on x86_64-unknown-linux-gnu.
>
> Ok to commit?
>
> -Maxim
>
>

Ping.

-Maxim

[-- Attachment #2: ssp_asan-6.diff --]
[-- Type: text/x-patch, Size: 3679 bytes --]

gcc/ChangeLog:

2015-02-09  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	PR sanitizer/64820
        * cfgexpand.c (align_base): New function.
        (alloc_stack_frame_space): Call it.
        (expand_stack_vars): Align prev_frame to be sure
        data->asan_vec elements aligned properly.

gcc/testsuite/ChangeLog:

2015-02-09  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	PR sanitizer/64820
        * c-c++-common/asan/pr64820.c: New test.

diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 7dfe1f6..7845a17 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -282,6 +282,15 @@ align_local_variable (tree decl)
   return align / BITS_PER_UNIT;
 }
 
+/* Align given offset BASE with ALIGN.  Truncate up if ALIGN_UP is true,
+   down otherwise.  Return truncated BASE value.  */
+
+static inline unsigned HOST_WIDE_INT
+align_base (HOST_WIDE_INT base, unsigned HOST_WIDE_INT align, bool align_up)
+{
+  return align_up ? (base + align - 1) & -align : base & -align;
+}
+
 /* Allocate SIZE bytes at byte alignment ALIGN from the stack frame.
    Return the frame offset.  */
 
@@ -293,17 +302,15 @@ alloc_stack_frame_space (HOST_WIDE_INT size, unsigned HOST_WIDE_INT align)
   new_frame_offset = frame_offset;
   if (FRAME_GROWS_DOWNWARD)
     {
-      new_frame_offset -= size + frame_phase;
-      new_frame_offset &= -align;
-      new_frame_offset += frame_phase;
+      new_frame_offset
+	= align_base (frame_offset - frame_phase - size,
+		      align, false) + frame_phase;
       offset = new_frame_offset;
     }
   else
     {
-      new_frame_offset -= frame_phase;
-      new_frame_offset += align - 1;
-      new_frame_offset &= -align;
-      new_frame_offset += frame_phase;
+      new_frame_offset
+	= align_base (frame_offset - frame_phase, align, true) + frame_phase;
       offset = new_frame_offset;
       new_frame_offset += size;
     }
@@ -1031,13 +1038,16 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
 	  base = virtual_stack_vars_rtx;
 	  if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && pred)
 	    {
-	      HOST_WIDE_INT prev_offset = frame_offset;
+	      HOST_WIDE_INT prev_offset
+		= align_base (frame_offset,
+			      MAX (alignb, ASAN_RED_ZONE_SIZE),
+			      FRAME_GROWS_DOWNWARD);
 	      tree repr_decl = NULL_TREE;
-
 	      offset
 		= alloc_stack_frame_space (stack_vars[i].size
 					   + ASAN_RED_ZONE_SIZE,
 					   MAX (alignb, ASAN_RED_ZONE_SIZE));
+
 	      data->asan_vec.safe_push (prev_offset);
 	      data->asan_vec.safe_push (offset + stack_vars[i].size);
 	      /* Find best representative of the partition.
diff --git a/gcc/testsuite/c-c++-common/asan/pr64820.c b/gcc/testsuite/c-c++-common/asan/pr64820.c
new file mode 100644
index 0000000..885a662
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr64820.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fstack_protector } */
+/* { dg-options "-fstack-protector-strong" } */
+/* { dg-set-target-env-var ASAN_OPTIONS "detect_stack_use_after_return=1" } */
+/* { dg-shouldfail "asan" } */
+
+__attribute__((noinline))
+char *Ident(char *x) {
+  return x;
+}
+
+__attribute__((noinline))
+char *Func1() {
+  char local[1 << 12];
+  return Ident(local);
+}
+
+__attribute__((noinline))
+void Func2(char *x) {
+  *x = 1;
+}
+int main(int argc, char **argv) {
+  Func2(Func1());
+  return 0;
+}
+
+/* { dg-output "AddressSanitizer: stack-use-after-return on address 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "WRITE of size 1 at .* thread T0.*" } */
+/* { dg-output "    #0.*(Func2)?.*pr64820.(c:21)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Ping v3] [PATCH PR64820] Fix ASan UAR detection fails on 32-bit targets if SSP is enabled.
  2015-02-25 14:50   ` [Ping v2] " Maxim Ostapenko
@ 2015-03-03  8:33     ` Maxim Ostapenko
  2015-03-10 17:43       ` [Ping v4] " Maxim Ostapenko
  0 siblings, 1 reply; 6+ messages in thread
From: Maxim Ostapenko @ 2015-03-03  8:33 UTC (permalink / raw)
  To: GCC Patches; +Cc: Yury Gribov, Slava Garbuzov

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


On 02/25/2015 05:40 PM, Maxim Ostapenko wrote:
> On 02/16/2015 10:58 AM, Maxim Ostapenko wrote:
>> Hi,
>>
>> when testing I noticed, that if compile with both -fsanitize=address and
>> -fstack-protector for 32-bit architectures and run with
>> ASAN_OPTIONS=detect_stack_use_after_return=1, libsanitizer fails with:
>>
>>   ==7299==AddressSanitizer CHECK failed:
>> /home/max/workspace/downloads/gcc/libsanitizer/asan/asan_poisoning.cc:25
>> "((AddrIsAlignedByGranularity(addr + size))) != (0)" (0x0, 0x0)
>>      #0 0xf72d8afc in AsanCheckFailed
>> /home/max/workspace/downloads/gcc/libsanitizer/asan/asan_rtl.cc:68
>>      #1 0xf72dda89 in __sanitizer::CheckFailed(char const*, int, char
>> const*, unsigned long long, unsigned long long)
>> /home/max/workspace/downloads/gcc/libsanitizer/sanitizer_common/sanitizer_common.cc:72 
>>
>>
>> This happens because ssp inserts a stack guard into a function, that
>> confuses asan_emit_stack_protection to calculate right size parameter
>> for asan_stack_malloc.
>>
>> This tiny patch resolves the issue.
>>
>> Regtested with make -j12 -k check
>> RUNTESTFLAGS='--target_board=unix\{-m32,-m64\}' on 
>> x86_64-unknown-linux-gnu.
>>
>> Bootstrapped, ASan-bootstrapped on x86_64-unknown-linux-gnu.
>>
>> Ok to commit?
>>
>> -Maxim
>>
>>
>
> Ping.
>
> -Maxim

Ping.

-Maxim


[-- Attachment #2: ssp_asan-6.diff --]
[-- Type: text/x-patch, Size: 3679 bytes --]

gcc/ChangeLog:

2015-03-03  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	PR sanitizer/64820
        * cfgexpand.c (align_base): New function.
        (alloc_stack_frame_space): Call it.
        (expand_stack_vars): Align prev_frame to be sure
        data->asan_vec elements aligned properly.

gcc/testsuite/ChangeLog:

2015-03-03  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	PR sanitizer/64820
        * c-c++-common/asan/pr64820.c: New test.

diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 7dfe1f6..7845a17 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -282,6 +282,15 @@ align_local_variable (tree decl)
   return align / BITS_PER_UNIT;
 }
 
+/* Align given offset BASE with ALIGN.  Truncate up if ALIGN_UP is true,
+   down otherwise.  Return truncated BASE value.  */
+
+static inline unsigned HOST_WIDE_INT
+align_base (HOST_WIDE_INT base, unsigned HOST_WIDE_INT align, bool align_up)
+{
+  return align_up ? (base + align - 1) & -align : base & -align;
+}
+
 /* Allocate SIZE bytes at byte alignment ALIGN from the stack frame.
    Return the frame offset.  */
 
@@ -293,17 +302,15 @@ alloc_stack_frame_space (HOST_WIDE_INT size, unsigned HOST_WIDE_INT align)
   new_frame_offset = frame_offset;
   if (FRAME_GROWS_DOWNWARD)
     {
-      new_frame_offset -= size + frame_phase;
-      new_frame_offset &= -align;
-      new_frame_offset += frame_phase;
+      new_frame_offset
+	= align_base (frame_offset - frame_phase - size,
+		      align, false) + frame_phase;
       offset = new_frame_offset;
     }
   else
     {
-      new_frame_offset -= frame_phase;
-      new_frame_offset += align - 1;
-      new_frame_offset &= -align;
-      new_frame_offset += frame_phase;
+      new_frame_offset
+	= align_base (frame_offset - frame_phase, align, true) + frame_phase;
       offset = new_frame_offset;
       new_frame_offset += size;
     }
@@ -1031,13 +1038,16 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
 	  base = virtual_stack_vars_rtx;
 	  if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && pred)
 	    {
-	      HOST_WIDE_INT prev_offset = frame_offset;
+	      HOST_WIDE_INT prev_offset
+		= align_base (frame_offset,
+			      MAX (alignb, ASAN_RED_ZONE_SIZE),
+			      FRAME_GROWS_DOWNWARD);
 	      tree repr_decl = NULL_TREE;
-
 	      offset
 		= alloc_stack_frame_space (stack_vars[i].size
 					   + ASAN_RED_ZONE_SIZE,
 					   MAX (alignb, ASAN_RED_ZONE_SIZE));
+
 	      data->asan_vec.safe_push (prev_offset);
 	      data->asan_vec.safe_push (offset + stack_vars[i].size);
 	      /* Find best representative of the partition.
diff --git a/gcc/testsuite/c-c++-common/asan/pr64820.c b/gcc/testsuite/c-c++-common/asan/pr64820.c
new file mode 100644
index 0000000..885a662
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr64820.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fstack_protector } */
+/* { dg-options "-fstack-protector-strong" } */
+/* { dg-set-target-env-var ASAN_OPTIONS "detect_stack_use_after_return=1" } */
+/* { dg-shouldfail "asan" } */
+
+__attribute__((noinline))
+char *Ident(char *x) {
+  return x;
+}
+
+__attribute__((noinline))
+char *Func1() {
+  char local[1 << 12];
+  return Ident(local);
+}
+
+__attribute__((noinline))
+void Func2(char *x) {
+  *x = 1;
+}
+int main(int argc, char **argv) {
+  Func2(Func1());
+  return 0;
+}
+
+/* { dg-output "AddressSanitizer: stack-use-after-return on address 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "WRITE of size 1 at .* thread T0.*" } */
+/* { dg-output "    #0.*(Func2)?.*pr64820.(c:21)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Ping v4] [PATCH PR64820] Fix ASan UAR detection fails on 32-bit targets if SSP is enabled.
  2015-03-03  8:33     ` [Ping v3] " Maxim Ostapenko
@ 2015-03-10 17:43       ` Maxim Ostapenko
  0 siblings, 0 replies; 6+ messages in thread
From: Maxim Ostapenko @ 2015-03-10 17:43 UTC (permalink / raw)
  To: GCC Patches; +Cc: Yury Gribov, Slava Garbuzov

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



On 02/25/2015 05:40 PM, Maxim Ostapenko wrote:
> On 02/16/2015 10:58 AM, Maxim Ostapenko wrote:
>> Hi,
>>
>> when testing I noticed, that if compile with both -fsanitize=address and
>> -fstack-protector for 32-bit architectures and run with
>> ASAN_OPTIONS=detect_stack_use_after_return=1, libsanitizer fails with:
>>
>>   ==7299==AddressSanitizer CHECK failed:
>> /home/max/workspace/downloads/gcc/libsanitizer/asan/asan_poisoning.cc:25
>> "((AddrIsAlignedByGranularity(addr + size))) != (0)" (0x0, 0x0)
>>      #0 0xf72d8afc in AsanCheckFailed
>> /home/max/workspace/downloads/gcc/libsanitizer/asan/asan_rtl.cc:68
>>      #1 0xf72dda89 in __sanitizer::CheckFailed(char const*, int, char
>> const*, unsigned long long, unsigned long long)
>> /home/max/workspace/downloads/gcc/libsanitizer/sanitizer_common/sanitizer_common.cc:72
>>
>>
>> This happens because ssp inserts a stack guard into a function, that
>> confuses asan_emit_stack_protection to calculate right size parameter
>> for asan_stack_malloc.
>>
>> This tiny patch resolves the issue.
>>
>> Regtested with make -j12 -k check
>> RUNTESTFLAGS='--target_board=unix\{-m32,-m64\}' on
>> x86_64-unknown-linux-gnu.
>>
>> Bootstrapped, ASan-bootstrapped on x86_64-unknown-linux-gnu.
>>
>> Ok to commit?
>>
>> -Maxim
>>
>>
>
> Ping.
>
> -Maxim

Ping.

-Maxim





[-- Attachment #2: ssp_asan-6.diff --]
[-- Type: text/x-patch, Size: 3680 bytes --]

gcc/ChangeLog:

2015-03-10  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	PR sanitizer/64820
        * cfgexpand.c (align_base): New function.
        (alloc_stack_frame_space): Call it.
        (expand_stack_vars): Align prev_frame to be sure
        data->asan_vec elements aligned properly.

gcc/testsuite/ChangeLog:

2015-03-10  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	PR sanitizer/64820
        * c-c++-common/asan/pr64820.c: New test.

diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 7dfe1f6..7845a17 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -282,6 +282,15 @@ align_local_variable (tree decl)
   return align / BITS_PER_UNIT;
 }
 
+/* Align given offset BASE with ALIGN.  Truncate up if ALIGN_UP is true,
+   down otherwise.  Return truncated BASE value.  */
+
+static inline unsigned HOST_WIDE_INT
+align_base (HOST_WIDE_INT base, unsigned HOST_WIDE_INT align, bool align_up)
+{
+  return align_up ? (base + align - 1) & -align : base & -align;
+}
+
 /* Allocate SIZE bytes at byte alignment ALIGN from the stack frame.
    Return the frame offset.  */
 
@@ -293,17 +302,15 @@ alloc_stack_frame_space (HOST_WIDE_INT size, unsigned HOST_WIDE_INT align)
   new_frame_offset = frame_offset;
   if (FRAME_GROWS_DOWNWARD)
     {
-      new_frame_offset -= size + frame_phase;
-      new_frame_offset &= -align;
-      new_frame_offset += frame_phase;
+      new_frame_offset
+	= align_base (frame_offset - frame_phase - size,
+		      align, false) + frame_phase;
       offset = new_frame_offset;
     }
   else
     {
-      new_frame_offset -= frame_phase;
-      new_frame_offset += align - 1;
-      new_frame_offset &= -align;
-      new_frame_offset += frame_phase;
+      new_frame_offset
+	= align_base (frame_offset - frame_phase, align, true) + frame_phase;
       offset = new_frame_offset;
       new_frame_offset += size;
     }
@@ -1031,13 +1038,16 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
 	  base = virtual_stack_vars_rtx;
 	  if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && pred)
 	    {
-	      HOST_WIDE_INT prev_offset = frame_offset;
+	      HOST_WIDE_INT prev_offset
+		= align_base (frame_offset,
+			      MAX (alignb, ASAN_RED_ZONE_SIZE),
+			      FRAME_GROWS_DOWNWARD);
 	      tree repr_decl = NULL_TREE;
-
 	      offset
 		= alloc_stack_frame_space (stack_vars[i].size
 					   + ASAN_RED_ZONE_SIZE,
 					   MAX (alignb, ASAN_RED_ZONE_SIZE));
+
 	      data->asan_vec.safe_push (prev_offset);
 	      data->asan_vec.safe_push (offset + stack_vars[i].size);
 	      /* Find best representative of the partition.
diff --git a/gcc/testsuite/c-c++-common/asan/pr64820.c b/gcc/testsuite/c-c++-common/asan/pr64820.c
new file mode 100644
index 0000000..885a662
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/asan/pr64820.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-require-effective-target fstack_protector } */
+/* { dg-options "-fstack-protector-strong" } */
+/* { dg-set-target-env-var ASAN_OPTIONS "detect_stack_use_after_return=1" } */
+/* { dg-shouldfail "asan" } */
+
+__attribute__((noinline))
+char *Ident(char *x) {
+  return x;
+}
+
+__attribute__((noinline))
+char *Func1() {
+  char local[1 << 12];
+  return Ident(local);
+}
+
+__attribute__((noinline))
+void Func2(char *x) {
+  *x = 1;
+}
+int main(int argc, char **argv) {
+  Func2(Func1());
+  return 0;
+}
+
+/* { dg-output "AddressSanitizer: stack-use-after-return on address 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "WRITE of size 1 at .* thread T0.*" } */
+/* { dg-output "    #0.*(Func2)?.*pr64820.(c:21)?.*" } */
+/* { dg-output "is located in stack of thread T0 at offset.*" } */


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH PR64820] Fix ASan UAR detection fails on 32-bit targets if SSP is enabled.
  2015-02-09 11:04 [PATCH PR64820] Fix ASan UAR detection fails on 32-bit targets if SSP is enabled Maxim Ostapenko
  2015-02-16  7:58 ` [Ping] " Maxim Ostapenko
@ 2015-03-15 20:23 ` Richard Sandiford
  1 sibling, 0 replies; 6+ messages in thread
From: Richard Sandiford @ 2015-03-15 20:23 UTC (permalink / raw)
  To: Maxim Ostapenko; +Cc: GCC Patches, Yury Gribov, Slava Garbuzov

Maxim Ostapenko <m.ostapenko@partner.samsung.com> writes:
> @@ -293,17 +302,15 @@ alloc_stack_frame_space (HOST_WIDE_INT size, unsigned HOST_WIDE_INT align)
>    new_frame_offset = frame_offset;

Think this assignment is dead after your change.

>    if (FRAME_GROWS_DOWNWARD)
>      {
> -      new_frame_offset -= size + frame_phase;
> -      new_frame_offset &= -align;
> -      new_frame_offset += frame_phase;
> +      new_frame_offset
> +	= align_base (frame_offset - frame_phase - size,
> +		      align, false) + frame_phase;
>        offset = new_frame_offset;
>      }
>    else
>      {
> -      new_frame_offset -= frame_phase;
> -      new_frame_offset += align - 1;
> -      new_frame_offset &= -align;
> -      new_frame_offset += frame_phase;
> +      new_frame_offset
> +	= align_base (frame_offset - frame_phase, align, true) + frame_phase;
>        offset = new_frame_offset;
>        new_frame_offset += size;
>      }

(Patch looks good to me otherwise FWIW.)

Thanks,
Richard

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-03-15 20:23 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-09 11:04 [PATCH PR64820] Fix ASan UAR detection fails on 32-bit targets if SSP is enabled Maxim Ostapenko
2015-02-16  7:58 ` [Ping] " Maxim Ostapenko
2015-02-25 14:50   ` [Ping v2] " Maxim Ostapenko
2015-03-03  8:33     ` [Ping v3] " Maxim Ostapenko
2015-03-10 17:43       ` [Ping v4] " Maxim Ostapenko
2015-03-15 20:23 ` Richard Sandiford

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).