On Aug 6, 2014, at 2:57 AM, Benny Baumann <[email protected]> wrote:
> Dear OpenBSD folks,
>
> I've been following the development of LibReSSL and when testing
> LibReSSL (the portable releases) on my Linux box (Lubuntu 14.04, Linux
> Kernel 3.16, GCC 4.9) I noticed the following (kinda) odd behaviour:
>
> I'm compiling LibReSSL with the following command lines:
> automake
> CFLAGS="-O3 -flto -fsanitize=address -Wall -march=native -mtune=native
> -g -ggdb3" LDFLAGS="$CFLAGS" ./configure
> make clean
> make all
> make check
>
> On LibReSSL 2.0.2:
> Everything works, tests run without problems, everything is fine.
>
> On LibReSSL 2.0.3 AND 2.0.4:
> Everything fine EXCEPT the test for explicit_bzero failing with an
> address sanitizing error in memmem (when looking for the secret in the
> buffer on line 132.
Hi Benny,
gcc is reserving some bytes at the beginning of the stack buffer, and
the test's scan is triggering this warning when the test scans the
signal stack for the secret bytes. Both the test and the gcc check are
working as expected, but obviously butt heads.
We should probably not assume all bytes of the signal stack buffer are
accessible while we are on it.
Matthew, does a change like below preserve the original intent of the
test?
--- 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 ...
>
> There's also another interesting message while linking, but IMHO that
> seems unrelated:
> ---
> CCLD libcrypto.la
> bio/.libs/libcrypto_la-b_dump.o (symbol from plugin): warning: memset
> used with constant zero length parameter; this could be due to
> transposed parameters
gcc and lto allow for constant propagation to create specialized versions
of functions with constant arguments. In this case, it is the call to:
BIO_dump_indent_cb(cb, u, s, len, 0);
that is the culprit. This is not a bug necessarily, but gcc could create
slightly more optimal code if we guarded the memset with an 'if (indent)'
> ---
> No such warning is issued for BIO_dump (b_dump.c) and following the
> code paths there getting the length to zero does not seem possible based
> on the source.
>
> Kind regards,
> BenBE.
>
> [demime 1.01d removed an attachment of type application/pgp-signature which
> had a name of signature.asc]