Created attachment 30902 [details] Repro Gcc seems to generate mismatched prologue/epilogue code to poison/unpoison stack frame for the attached source code when I compile it with $ ~/install/gcc-master-arm/bin/arm-v7a15v3r2-linux-gnueabi-gcc bad.i -O0 -S -fsanitize=address Prologue seems to poison words at frame_shadow_base + { 0, 4, 8, 12, 16, 24, 28}: add r4, r3, #536870912 ldr r3, .L3+8 str r3, [r4] ldr r3, .L3+12 str r3, [r4, #4] ldr r3, .L3+16 str r3, [r4, #8] ldr r3, .L3+20 str r3, [r4, #12] ldr r3, .L3+16 str r3, [r4, #16] ldr r3, .L3+20 str r3, [r4, #24] ldr r3, .L3+24 str r3, [r4, #28] Whereas epilogue poisons frame_shadow_base + { 0, 4, 8, 12, 16, 40, 44}: add r3, r4, #20 .L1: mov r2, #0 str r2, [r4] add r4, r4, #4 cmp r4, r3 bcc .L1 add r3, r4, #24 ; r3 gets invalid value here mov r2, #0 strb r2, [r3] add r3, r3, #1 mov r2, #0 strb r2, [r3] add r3, r3, #1 mov r2, #0 strb r2, [r3] add r3, r3, #1 mov r2, #0 strb r2, [r3] add r3, r3, #1 mov r2, #0 strb r2, [r3] add r3, r3, #1 mov r2, #0 strb r2, [r3] add r3, r3, #1 mov r2, #0 strb r2, [r3] add r3, r3, #1 mov r2, #0 strb r2, [r3] This causes some shadow bytes to remain set after function returns. Those may trigger incorrect Asan errors later. -Y PS: my configuration: * GCC version: trunk, September 24 * OS: Ubuntu 12.04 * GCC configuration string: ~/gcc/gcc-master/configure --target=arm-v7a15v3r2-linux-gnueabi --prefix=/home/ygribov/install/gcc-master-arm --disable-libmudflap --disable-libssp --disable-nls --enable-long-long --enable-languages=c,c++ --disable-bootstrap --disable-multilib --disable-libstdcxx --disable-libgcc --disable-libgomp --disable-libatomic --disable-libquadmath --disable-libstdc++-v3 --disable-libsanitizer --disable-libitm
Created attachment 30903 [details] Proposed patch
I've attached a simple patch which causes compiler new register to allocate new temp address register. I'll only be able to test it tomorrow though.
Created attachment 30908 [details] Test results Tests seem to pass both on x86_64 and on ARM (attached).
Thank you for reporting this bug. Please find my comments below, "y.gribov at samsung dot com" <gcc-bugzilla@gcc.gnu.org> a écrit: > Prologue seems to poison words at frame_shadow_base + { 0, 4, 8, 12, 16, 24, > 28}: Right. > > add r4, r3, #536870912 > ldr r3, .L3+8 > str r3, [r4] > ldr r3, .L3+12 > str r3, [r4, #4] > ldr r3, .L3+16 > str r3, [r4, #8] > ldr r3, .L3+20 > str r3, [r4, #12] > ldr r3, .L3+16 > str r3, [r4, #16] > ldr r3, .L3+20 > str r3, [r4, #24] > ldr r3, .L3+24 > str r3, [r4, #28] > > Whereas epilogue poisons frame_shadow_base + { 0, 4, 8, 12, 16, 40, 44}: I guess you mean *un*poison here. > add r3, r4, #20 > .L1: > mov r2, #0 > str r2, [r4] > add r4, r4, #4 > cmp r4, r3 > bcc .L1 My understanding is that in the loop above, we are setting the memory pointed to by frame_shadow_base + { 0, 4, 8, 12, 16} to zero. And in the code below, we are preparing to set the memory pointed to by frame_shadow_base + {24, 28} to zero. > add r3, r4, #24 ; r3 gets invalid value here Why is r3 invalid? It's being set to #24, so that the strb r2, [r3] below writes a zero byte to [r4,#24]. Or what am I missing? > mov r2, #0 > strb r2, [r3] > add r3, r3, #1 > mov r2, #0 > strb r2, [r3] > add r3, r3, #1 > mov r2, #0 > strb r2, [r3] > add r3, r3, #1 > mov r2, #0 > strb r2, [r3] > add r3, r3, #1 > mov r2, #0 > strb r2, [r3] > add r3, r3, #1 > mov r2, #0 > strb r2, [r3] > add r3, r3, #1 > mov r2, #0 > strb r2, [r3] > add r3, r3, #1 > mov r2, #0 > strb r2, [r3] > > This causes some shadow bytes to remain set after function returns. Those may > trigger incorrect Asan errors later. I am guessing that you have a short and self contained example of an asan error that is caused by a wrong epilogue. Would it be possible that you file it so that I can understand better what is going on? Thanks.
> I guess you mean *un*poison here. Right you are! > My understanding is that in the loop above, we are setting the memory > pointed to by frame_shadow_base + { 0, 4, 8, 12, 16} to zero. > > And in the code below, we are preparing to set the memory pointed to by > frame_shadow_base + {24, 28} to zero. Exactly. > add r3, r4, #24 ; r3 gets invalid value here > Why is r3 invalid? It's being set to #24, > so that the strb r2, [r3] below writes a zero byte to [r4,#24]. Not really - it's set to #40 because r4 was changed to #16 inside the loop > Would it be possible that you file it > so that I can understand better what is going on? Sure - simply compile the attached repro with `-O0 -fsanitize-address'. But note that you need to use ARM target because x86 does not trigger this bug (most probably because it uses different code path in asan_clear_shadow). -Y
Dodji, Let me know if I can provide additional info which may help to debug/fix this. -Y
Created attachment 30946 [details] Standalone repro Dodji, It has just occured to me that you probably want an executable repro with nice runtime error. Here is the first try (mainly a harness around the previous repro). The testcase firstly runs function bad() which fails to unpoison frame shadow. It then tries to accesses bad()'s stack which triggers Asan error. Simply compile the attached file with `-fsanitize=address -O2' and run it on ARM target. As I mentioned before, the stack shadow gets borked so by default you'll get an abort from Asan runtime: ================================================================= ==3366== ERROR: AddressSanitizer: stack-buffer-overflow on address 0xbefff797 at pc 0x8670 bp 0xbefff7ac sp 0xbefff7a4 READ of size 1 at 0xbefff797 thread T0 #0 0x866f (/dtv/usb/sda1/a.out+0x866f) #1 0x41632bcb (/mtd_exe/lib/libc-2.14.1.so+0x17bcb) ==3366== AddressSanitizer CHECK failed: /home/ygribov/gcc/gcc-master/libsanitizer/asan/asan_report.cc:250 "((name_end)) != (0)" (0x0, 0x0) #0 0x4003ace7 (/dtv/usb/sda1/libasan.so.0+0x12ce7) #1 0x400436fb (/dtv/usb/sda1/libasan.so.0+0x1b6fb) #2 0x4004121b (/dtv/usb/sda1/libasan.so.0+0x1921b) #3 0x4004136f (/dtv/usb/sda1/libasan.so.0+0x1936f) #4 0x40041feb (/dtv/usb/sda1/libasan.so.0+0x19feb) #5 0x4003b18b (/dtv/usb/sda1/libasan.so.0+0x1318b) #6 0x866f (/dtv/usb/sda1/a.out+0x866f) #7 0x41632bcb (/mtd_exe/lib/libc-2.14.1.so+0x17bcb) This is already a sign of invalid instrumentation. To get a more informative output, replace CHECK(name_end); with if(!name_end) return true; in libsanitizer/asan/asan_report.cc: ================================================================= ==3468== ERROR: AddressSanitizer: stack-buffer-overflow on address 0xbefff797 at pc 0x8670 bp 0xbefff7ac sp 0xbefff7a4 READ of size 1 at 0xbefff797 thread T0 #0 0x866f (/dtv/usb/sda1/a.out+0x866f) #1 0x41632bcb (/mtd_exe/lib/libc-2.14.1.so+0x17bcb) Shadow bytes around the buggy address: 0x37dffea0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x37dffeb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x37dffec0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x37dffed0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x37dffee0: 00 00 00 00 00 00 00 00 00 00 00 00 f4 f4 f4 f3 =>0x37dffef0: f3 f3[f3]00 00 00 f1 f1 f1 f1 01 f4 f4 f4 f3 00 0x37dfff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x37dfff10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x37dfff20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x37dfff30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x37dfff40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap righ redzone: fb Freed Heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 ASan internal: fe ==3468== ABORTING You can see that bad() function has not cleared the poisoned bytes. -Y
Created attachment 31032 [details] Changelog entry Adding Changelog entry.
Thread on lists. http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00380.html
Author: ygribov Date: Thu Oct 31 12:10:01 2013 New Revision: 204251 URL: http://gcc.gnu.org/viewcvs?rev=204251&root=gcc&view=rev Log: 2013-10-31 Richard Sandiford <rsandifo@linux.vnet.ibm.com> Yury Gribov <y.gribov@samsung.com> PR sanitizer/58543 * asan.c (asan_clear_shadow): Allocate a new vreg for temporary shadow pointer to avoid clobbering the main one. Modified: trunk/gcc/ChangeLog trunk/gcc/asan.c
Fixed by afore-mentioned commit.
Author: yroux Date: Mon Aug 11 21:57:46 2014 New Revision: 213841 URL: https://gcc.gnu.org/viewcvs?rev=213841&root=gcc&view=rev Log: 2014-08-11 Michael Collison <michael.collison@linaro.org> Backport from trunk r204251 2013-10-31 Richard Sandiford <rsandifo@linux.vnet.ibm.com> Yury Gribov <y.gribov@samsung.com> PR sanitizer/58543 * asan.c (asan_clear_shadow): Allocate a new vreg for temporary shadow pointer to avoid clobbering the main one. Modified: branches/linaro/gcc-4_8-branch/gcc/ChangeLog.linaro branches/linaro/gcc-4_8-branch/gcc/asan.c