[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