From 78a52f19bb207d1c736f1d5362e01f338d78645f Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Fri, 24 Jun 2016 17:14:14 -0700 Subject: [PATCH] Attempt to use arc4random where getauxval(AT_RANDOM) is used. When arc4random can get entropy (which is true for basically everyone but init on kernels that don't support getrandom), use it instead of AT_RANDOM. Bug: http://b/29622562 Change-Id: I6932803af2c477e65562ff531bd959f199fad1df --- libc/Android.bp | 1 + libc/bionic/__libc_init_main_thread.cpp | 5 ++- libc/bionic/bionic_arc4random.cpp | 58 +++++++++++++++++++++++++++++++++ libc/bionic/setjmp_cookie.cpp | 8 ++--- libc/private/bionic_arc4random.h | 45 +++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 7 deletions(-) create mode 100644 libc/bionic/bionic_arc4random.cpp create mode 100644 libc/private/bionic_arc4random.h diff --git a/libc/Android.bp b/libc/Android.bp index 4fcd83e05..b7a1bb508 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -1211,6 +1211,7 @@ cc_library_static { "bionic/arpa_inet.cpp", "bionic/assert.cpp", "bionic/atof.cpp", + "bionic/bionic_arc4random.cpp", "bionic/bionic_netlink.cpp", "bionic/bionic_systrace.cpp", "bionic/bionic_time_conversions.cpp", diff --git a/libc/bionic/__libc_init_main_thread.cpp b/libc/bionic/__libc_init_main_thread.cpp index 2643eeef9..0647387e4 100644 --- a/libc/bionic/__libc_init_main_thread.cpp +++ b/libc/bionic/__libc_init_main_thread.cpp @@ -29,6 +29,7 @@ #include "libc_init_common.h" #include "private/KernelArgumentBlock.h" +#include "private/bionic_arc4random.h" #include "private/bionic_auxv.h" #include "private/bionic_globals.h" #include "private/bionic_ssp.h" @@ -41,9 +42,7 @@ extern "C" int __set_tid_address(int* tid_address); uintptr_t __stack_chk_guard = 0; void __libc_init_global_stack_chk_guard(KernelArgumentBlock& args) { - // AT_RANDOM is a pointer to 16 bytes of randomness on the stack. - // Take the first 4/8 for the -fstack-protector implementation. - __stack_chk_guard = *reinterpret_cast(args.getauxval(AT_RANDOM)); + __libc_safe_arc4random_buf(&__stack_chk_guard, sizeof(__stack_chk_guard), args); } // Setup for the main thread. For dynamic executables, this is called by the diff --git a/libc/bionic/bionic_arc4random.cpp b/libc/bionic/bionic_arc4random.cpp new file mode 100644 index 000000000..d20cb6803 --- /dev/null +++ b/libc/bionic/bionic_arc4random.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "private/bionic_arc4random.h" + +#include +#include +#include +#include +#include + +#include "private/KernelArgumentBlock.h" +#include "private/libc_logging.h" + +void __libc_safe_arc4random_buf(void* buf, size_t n, KernelArgumentBlock& args) { + static bool have_getrandom = syscall(SYS_getrandom, nullptr, 0, 0) == -1 && errno != ENOSYS; + static bool have_urandom = access("/dev/urandom", R_OK) == 0; + static size_t at_random_bytes_consumed = 0; + + if (have_getrandom || have_urandom) { + arc4random_buf(buf, n); + return; + } + + if (at_random_bytes_consumed + n > 16) { + __libc_fatal("ran out of AT_RANDOM bytes, have %zu, requested %zu", + 16 - at_random_bytes_consumed, n); + } + + memcpy(buf, reinterpret_cast(args.getauxval(AT_RANDOM)) + at_random_bytes_consumed, n); + at_random_bytes_consumed += n; + return; +} diff --git a/libc/bionic/setjmp_cookie.cpp b/libc/bionic/setjmp_cookie.cpp index 3be675aab..4fa68c2bd 100644 --- a/libc/bionic/setjmp_cookie.cpp +++ b/libc/bionic/setjmp_cookie.cpp @@ -34,14 +34,14 @@ #include #include +#include "private/bionic_arc4random.h" #include "private/bionic_globals.h" #include "private/libc_logging.h" #include "private/KernelArgumentBlock.h" -void __libc_init_setjmp_cookie(libc_globals* globals, - KernelArgumentBlock& args) { - char* random_data = reinterpret_cast(args.getauxval(AT_RANDOM)); - long value = *reinterpret_cast(random_data + 8); +void __libc_init_setjmp_cookie(libc_globals* globals, KernelArgumentBlock& args) { + long value; + __libc_safe_arc4random_buf(&value, sizeof(value), args); // Mask off the last bit to store the signal flag. globals->setjmp_cookie = value & ~1; diff --git a/libc/private/bionic_arc4random.h b/libc/private/bionic_arc4random.h new file mode 100644 index 000000000..d26a4e755 --- /dev/null +++ b/libc/private/bionic_arc4random.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _PRIVATE_BIONIC_ARC4RANDOM_H_ +#define _PRIVATE_BIONIC_ARC4RANDOM_H_ + +#include + +#include "private/KernelArgumentBlock.h" + +/* + * arc4random aborts if it's unable to fetch entropy, which is always the case + * for init on devices without getrandom(2), since /dev/random hasn't been + * created yet. Provide a wrapper function that falls back to AT_RANDOM if + * we don't have getrandom and /dev/urandom is missing. + */ + +void __libc_safe_arc4random_buf(void* buf, size_t n, KernelArgumentBlock& args); + +#endif -- 2.11.0