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
gcc/ChangeLog:
2015-03-03 Max Ostapenko <m.ostape...@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.ostape...@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.*" } */