On Wed, Aug 6, 2014 at 10:37 AM, Matthew Dempsky <[email protected]>
wrote:

> On Wed, Aug 6, 2014 at 6:00 AM, Brent Cook <[email protected]> wrote:
> > Matthew, does a change like below preserve the original intent of the
> > test?
>
> No, this change causes undefined behavior using a pointer to an object
> past when its lifetime ended, which is specifically what
> explicit_bzero.c is written to avoid by using signal handlers and the
> altstack.
>
> I'm pretty sure this is just a false positive from address sanitizer
> due to it not understanding alternate stacks.
>
>
Which object is used past its lifetime? buf is local to the function, and
secret is a static global.

Enabling the stack protector code really does shift buf by 112 bytes on the
signal stack, so I think its more likely working and inserting some guards
at the head and tail of the stack signal stack.

Sorry in advance if I'm being dense here and not seeing the problem. I do
wonder why folks are so hell bent on enabling LTO when there are quite a
few lower-hanging fruits for -portable optimization :)


> > --- a/src/regress/lib/libc/explicit_bzero/explicit_bzero.c
> > +++ b/src/regress/lib/libc/explicit_bzero/explicit_bzero.c
> > @@ -129,7 +129,7 @@ test_without_bzero()
> >         char buf[SECRETBYTES];
> >         assert_on_stack();
> >         populate_secret(buf, sizeof(buf));
> > -       char *res = memmem(altstack, sizeof(altstack), buf, sizeof(buf));
> > +       char *res = memmem(buf, sizeof(buf), secret, sizeof(secret));
> >         ASSERT_NE(NULL, res);
> >         return (res);
> >  }
> > @@ -140,7 +140,7 @@ test_with_bzero()
> >         char buf[SECRETBYTES];
> >         assert_on_stack();
> >         populate_secret(buf, sizeof(buf));
> > -       char *res = memmem(altstack, sizeof(altstack), buf, sizeof(buf));
> > +       char *res = memmem(buf, sizeof(buf), secret, sizeof(secret));
> >         ASSERT_NE(NULL, res);
> >         explicit_bzero(buf, sizeof(buf));
> >         return (res);
> >
> >> The error report by ASan is as follows:
> >> =================================================================
> >> ==27814== ERROR: AddressSanitizer: stack-buffer-underflow on address
> >> 0x000000605fe0 at pc 0x401587 bp 0x605fa0 sp 0x605f98
> >> READ of size 1 at 0x000000605fe0 thread T0
> >>    #0 0x401586
> >> (/usr/src/libressl-2.0.4/tests/.libs/lt-explicit_bzero+0x401586)
> >>    #1 0x401661
> >> (/usr/src/libressl-2.0.4/tests/.libs/lt-explicit_bzero+0x401661)
> >>    #2 0x7fd8678e0fff (/lib/x86_64-linux-gnu/libc-2.19.so+0x36fff)
> >>    #3 0x7fd8678e12e5 (/lib/x86_64-linux-gnu/libc-2.19.so+0x372e5)
> >>    #4 0x401cba
> >> (/usr/src/libressl-2.0.4/tests/.libs/lt-explicit_bzero+0x401cba)
> >>    #5 0x400f32
> >> (/usr/src/libressl-2.0.4/tests/.libs/lt-explicit_bzero+0x400f32)
> >>    #6 0x7fd8678cbec4 (/lib/x86_64-linux-gnu/libc-2.19.so+0x21ec4)
> >>    #7 0x401044
> >> (/usr/src/libressl-2.0.4/tests/.libs/lt-explicit_bzero+0x401044)
> >> 0x000000605fe0 is located 6560 bytes inside of global variable 'altstack
> >> (/tmp/ccJge4UH.ltrans0.o)' (0x604640) of size 9216
> >> Shadow bytes around the buggy address:
> >>  0x0000800b8ba0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >>  0x0000800b8bb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >>  0x0000800b8bc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >>  0x0000800b8bd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >>  0x0000800b8be0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >> =>0x0000800b8bf0: 00 00 00 00 00 00 00 00 00 00 00 00[f1]f1 f1 f1
> >>  0x0000800b8c00: 00 00 00 f4 f2 f2 f2 f2 00 00 00 00 00 00 00 00
> >>  0x0000800b8c10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >>  0x0000800b8c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >>  0x0000800b8c30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
> >>  0x0000800b8c40: 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
> >> ==27814== ABORTING
> >>
> >> The most interesting part here is that LibReSSL 2.0.2 used the exact
> >> same code for the testcase but works. Thus I'm more likely suspecting a
> >> GCC or ASan bug here, but you never know ...

Reply via email to