OSDN Git Service

Attempt to use arc4random where getauxval(AT_RANDOM) is used.
authorJosh Gao <jmgao@google.com>
Sat, 25 Jun 2016 00:14:14 +0000 (17:14 -0700)
committerJosh Gao <jmgao@google.com>
Thu, 1 Sep 2016 01:01:05 +0000 (18:01 -0700)
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
libc/bionic/__libc_init_main_thread.cpp
libc/bionic/bionic_arc4random.cpp [new file with mode: 0644]
libc/bionic/setjmp_cookie.cpp
libc/private/bionic_arc4random.h [new file with mode: 0644]

index 4fcd83e..b7a1bb5 100644 (file)
@@ -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",
index 2643eee..0647387 100644 (file)
@@ -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<uintptr_t*>(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 (file)
index 0000000..d20cb68
--- /dev/null
@@ -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 <errno.h>
+#include <stdlib.h>
+#include <sys/auxv.h>
+#include <syscall.h>
+#include <unistd.h>
+
+#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<char*>(args.getauxval(AT_RANDOM)) + at_random_bytes_consumed, n);
+  at_random_bytes_consumed += n;
+  return;
+}
index 3be675a..4fa68c2 100644 (file)
 #include <sys/auxv.h>
 #include <sys/cdefs.h>
 
+#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<char*>(args.getauxval(AT_RANDOM));
-  long value = *reinterpret_cast<long*>(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 (file)
index 0000000..d26a4e7
--- /dev/null
@@ -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 <stddef.h>
+
+#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