https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88277
Bug ID: 88277
Summary: ASAN stack poisoning is using unaligned stores on e.g.
x86_64
Product: gcc
Version: 9.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: sanitizer
Assignee: unassigned at gcc dot gnu.org
Reporter: marxin at gcc dot gnu.org
CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
jakub at gcc dot gnu.org, kcc at gcc dot gnu.org, marxin at
gcc dot gnu.org
Target Milestone: ---
Considering x86_64 and following example:
$ cat asan.c
void bar (void *a)
{
int *p = a;
*(p-1) = 123;
}
int
baz (void)
{
char e2[56];
bar (&e2[0]);
return 0;
}
int *p;
int main()
{
int a;
p = &a;
baz();
}
I see:
$ gcc asan.c -fsanitize=address &&
ASAN_OPTIONS=detect_stack_use_after_return=1 ./a.out
=================================================================
==21996==ERROR: AddressSanitizer: stack-buffer-underflow on address
0x7ffff2d0009c at pc 0x000000401195 bp 0x7fffffffda80 sp 0x7fffffffda78
WRITE of size 4 at 0x7ffff2d0009c thread T0
#0 0x401194 in bar (/home/marxin/Programming/testcases/a.out+0x401194)
#1 0x401227 in baz (/home/marxin/Programming/testcases/a.out+0x401227)
#2 0x401309 in main (/home/marxin/Programming/testcases/a.out+0x401309)
#3 0x7ffff6c71fea in __libc_start_main ../csu/libc-start.c:308
#4 0x401099 in _start (/home/marxin/Programming/testcases/a.out+0x401099)
Address 0x7ffff2d0009c is located in stack of thread T0 at offset 28 in frame
#0 0x4011ad in baz (/home/marxin/Programming/testcases/a.out+0x4011ad)
This frame has 1 object(s):
[32, 88) 'e2' <== Memory access at offset 28 underflows this variable
HINT: this may be a false positive if your program uses some custom stack
unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-underflow
(/home/marxin/Programming/testcases/a.out+0x401194) in bar
Shadow bytes around the buggy address:
0x10007e597fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007e597fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007e597fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007e597ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007e598000: f1 f1 f1 f1 04 f2 f2 f2 f3 f3 f3 f3 00 00 00 00
=>0x10007e598010: f1 f1 f1[f1]00 00 00 00 00 00 00 f2 f3 f3 f3 f3
0x10007e598020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007e598030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007e598040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007e598050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007e598060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
This is fine starting f3 at 0x10007e598010 line is aligned to 32B.
However:
$ gcc asan.c -fsanitize=address &&
ASAN_OPTIONS=detect_stack_use_after_return=0 ./a.out
=================================================================
==22038==ERROR: AddressSanitizer: stack-buffer-underflow on address
0x7fffffffdadc at pc 0x000000401195 bp 0x7fffffffda80 sp 0x7fffffffda78
WRITE of size 4 at 0x7fffffffdadc thread T0
#0 0x401194 in bar (/home/marxin/Programming/testcases/a.out+0x401194)
#1 0x401227 in baz (/home/marxin/Programming/testcases/a.out+0x401227)
#2 0x401309 in main (/home/marxin/Programming/testcases/a.out+0x401309)
#3 0x7ffff6c71fea in __libc_start_main ../csu/libc-start.c:308
#4 0x401099 in _start (/home/marxin/Programming/testcases/a.out+0x401099)
Address 0x7fffffffdadc is located in stack of thread T0 at offset 28 in frame
#0 0x4011ad in baz (/home/marxin/Programming/testcases/a.out+0x4011ad)
This frame has 1 object(s):
[32, 88) 'e2' <== Memory access at offset 28 underflows this variable
HINT: this may be a false positive if your program uses some custom stack
unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-underflow
(/home/marxin/Programming/testcases/a.out+0x401194) in bar
Shadow bytes around the buggy address:
0x10007fff7b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007fff7b10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007fff7b20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007fff7b30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007fff7b40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10007fff7b50: 00 00 00 00 00 00 00 00 f1 f1 f1[f1]00 00 00 00
0x10007fff7b60: 00 00 00 f2 f3 f3 f3 f3 00 00 00 00 00 00 f1 f1
0x10007fff7b70: f1 f1 04 f2 f2 f2 f3 f3 f3 f3 00 00 00 00 00 00
0x10007fff7b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007fff7b90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x10007fff7ba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
The first f3 byte is only aligned to 2B in shadow memory. And as we use movl
instructions, it's unaligned store:
movl $-202116109, 2147450888(%r12)
(gdb) p /x -202116109
$1 = 0xf3f3f3f3