[Bug sanitizer/82501] AddressSanitizer does not handle negative offset for first global variable
a.drobyshev at samsung dot com
gcc-bugzilla@gcc.gnu.org
Mon Feb 25 18:21:00 GMT 2019
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82501
--- Comment #19 from Andrey Drobyshev <a.drobyshev at samsung dot com> ---
(In reply to Martin Liška from comment #17)
> > 2. What should we do with sections like .data.rel.ro, .data.rel.ro.local?
> > They suffer from this bug too, but it's not that easy to put globals there,
> > as you must set various attributes onto decl to ensure it will receive the
> > right reloc value.
>
> Answer for this would be that we probably can't do that with approach #2 (as
> defined in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82501#c1). Btw. how
> can one hit an invalid memory in .data.rel.ro (or .data.rel.ro.local)?
Take a look:
$ cat data_rel_ro.c
extern int a;
int * const b = &a;
int *foo(void)
{
int **ptr = &b;
ptr--;
return *ptr;
}
$ cat main.c
int a = -1;
int *c;
extern int *foo(void);
int main(int argc, char *argv[])
{
c = foo();
return 0;
}
Now compile this thing with -fPIE (assuming we want ASLR):
$ gcc -fsanitize=address -fPIE data_rel_ro.c main.c
...and b is put to .data.rel.ro:
$ objdump -t a.out
a.out: file format elf64-x86-64
SYMBOL TABLE:
....
0000000000601040 g O .data.rel.ro 0000000000000008 b
....
foo() hits invalid memory to the left of b, but our patched ASan doesn't detect
(as expected though):
$ ./a.out
$
However, there's still a redzone to the right, as it should be:
$ cat data_rel_ro.c
extern int a;
int * const b = &a;
int *foo(void)
{
int **ptr = &b;
ptr++;
return *ptr;
}
$ ./a.out
==32200==ERROR: AddressSanitizer: global-buffer-overflow on address
0x000000601048 at pc 0x0000004007d8 bp 0x7ffee53dc6a0 sp 0x7ffee53dc680
READ of size 8 at 0x000000601048 thread T0
#0 0x4007d7 in foo /home/src/gcc/obj/data_rel_ro.c:8
#1 0x40082c in main /home/src/gcc/obj/main.c:8
#2 0x7f80ea98682f in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#3 0x4006b8 in _start (/home/src/gcc/obj/a.out+0x4006b8)
0x000000601048 is located 0 bytes to the right of global variable 'b' defined
in 'data_rel_ro.c:2:13' (0x601040) of size 8
SUMMARY: AddressSanitizer: global-buffer-overflow
/home/src/gcc/obj/data_rel_ro.c:8 in foo
Shadow bytes around the buggy address:
0x0000800b81b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800b81c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800b81d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800b81e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800b81f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0000800b8200: 00 00 00 00 00 00 00 00 00[f9]f9 f9 f9 f9 f9 f9
0x0000800b8210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800b8220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800b8230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800b8240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800b8250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
So I guess we still have to detect relocations. I cannot see limitations coming
particularly from approach #2 from
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82501#c1. We just need to pass the
right reloc value to categorize_decl_for_section().
More information about the Gcc-bugs
mailing list