DivestOS/Patches/LineageOS-14.1/android_bionic/0004-Add_random.h.patch
Tavi 0c88720caa
14.1: work on integrating hardened_malloc
untested as all currently supported 14.1 devices are 32-bit

Signed-off-by: Tavi <tavi@divested.dev>
2024-05-09 13:46:19 -04:00

518 lines
15 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Elliott Hughes <enh@google.com>
Date: Wed, 27 Sep 2017 16:33:35 -0700
Subject: [PATCH] Add <sys/random.h>.
iOS 10 has <sys/random.h> with getentropy, glibc >= 2.25 has
<sys/random.h> with getentropy and getrandom. (glibc also pollutes
<unistd.h>, but that seems like a bad idea.)
Also, all supported devices now have kernels with the getrandom system
call.
We've had these available internally for a while, but it seems like the
time is ripe to expose them.
Bug: http://b/67014255
Test: ran tests
Change-Id: I76dde1e3a2d0bc82777eea437ac193f96964f138
---
libc/SYSCALLS.TXT | 3 +
libc/arch-arm/syscalls/getrandom.S | 16 +++
libc/arch-arm64/syscalls/getrandom.S | 14 ++
libc/arch-mips/syscalls/getrandom.S | 19 +++
libc/arch-mips64/syscalls/getrandom.S | 25 ++++
libc/arch-x86/syscalls/getrandom.S | 39 ++++++
libc/arch-x86_64/syscalls/getrandom.S | 15 +++
libc/include/sys/random.h | 47 +++++++
libc/libc.arm.map | 2 +
libc/libc.arm64.map | 2 +
libc/libc.map.txt | 2 +
libc/libc.mips.map | 2 +
libc/libc.mips64.map | 2 +
libc/libc.x86.map | 2 +
libc/libc.x86_64.map | 2 +
.../android/include/openbsd-compat.h | 8 +-
tests/sys_random_test.cpp | 120 ++++++++++++++++++
17 files changed, 317 insertions(+), 3 deletions(-)
create mode 100644 libc/arch-arm/syscalls/getrandom.S
create mode 100644 libc/arch-arm64/syscalls/getrandom.S
create mode 100644 libc/arch-mips/syscalls/getrandom.S
create mode 100644 libc/arch-mips64/syscalls/getrandom.S
create mode 100644 libc/arch-x86/syscalls/getrandom.S
create mode 100644 libc/arch-x86_64/syscalls/getrandom.S
create mode 100644 libc/include/sys/random.h
create mode 100644 tests/sys_random_test.cpp
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index d5dd2063e..536216dba 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -348,3 +348,6 @@ int clock_gettime(clockid_t, timespec*) arm,mips,mips64
int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86,x86_64
int gettimeofday(timeval*, timezone*) arm,mips,mips64
int __gettimeofday:gettimeofday(timeval*, timezone*) arm64,x86,x86_64
+
+# <sys/random.h>
+ssize_t getrandom(void*, size_t, unsigned) all
diff --git a/libc/arch-arm/syscalls/getrandom.S b/libc/arch-arm/syscalls/getrandom.S
new file mode 100644
index 000000000..3f28af6f0
--- /dev/null
+++ b/libc/arch-arm/syscalls/getrandom.S
@@ -0,0 +1,16 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(getrandom)
+ mov ip, r7
+ .cfi_register r7, ip
+ ldr r7, =__NR_getrandom
+ swi #0
+ mov r7, ip
+ .cfi_restore r7
+ cmn r0, #(MAX_ERRNO + 1)
+ bxls lr
+ neg r0, r0
+ b __set_errno_internal
+END(getrandom)
diff --git a/libc/arch-arm64/syscalls/getrandom.S b/libc/arch-arm64/syscalls/getrandom.S
new file mode 100644
index 000000000..c8fe41ffd
--- /dev/null
+++ b/libc/arch-arm64/syscalls/getrandom.S
@@ -0,0 +1,14 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(getrandom)
+ mov x8, __NR_getrandom
+ svc #0
+
+ cmn x0, #(MAX_ERRNO + 1)
+ cneg x0, x0, hi
+ b.hi __set_errno_internal
+
+ ret
+END(getrandom)
diff --git a/libc/arch-mips/syscalls/getrandom.S b/libc/arch-mips/syscalls/getrandom.S
new file mode 100644
index 000000000..7a2f3b978
--- /dev/null
+++ b/libc/arch-mips/syscalls/getrandom.S
@@ -0,0 +1,19 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(getrandom)
+ .set noreorder
+ .cpload t9
+ li v0, __NR_getrandom
+ syscall
+ bnez a3, 1f
+ move a0, v0
+ j ra
+ nop
+1:
+ la t9,__set_errno_internal
+ j t9
+ nop
+ .set reorder
+END(getrandom)
diff --git a/libc/arch-mips64/syscalls/getrandom.S b/libc/arch-mips64/syscalls/getrandom.S
new file mode 100644
index 000000000..3c5b4673f
--- /dev/null
+++ b/libc/arch-mips64/syscalls/getrandom.S
@@ -0,0 +1,25 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(getrandom)
+ .set push
+ .set noreorder
+ li v0, __NR_getrandom
+ syscall
+ bnez a3, 1f
+ move a0, v0
+ j ra
+ nop
+1:
+ move t0, ra
+ bal 2f
+ nop
+2:
+ .cpsetup ra, t1, 2b
+ LA t9,__set_errno_internal
+ .cpreturn
+ j t9
+ move ra, t0
+ .set pop
+END(getrandom)
diff --git a/libc/arch-x86/syscalls/getrandom.S b/libc/arch-x86/syscalls/getrandom.S
new file mode 100644
index 000000000..2e8ebc955
--- /dev/null
+++ b/libc/arch-x86/syscalls/getrandom.S
@@ -0,0 +1,39 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(getrandom)
+ pushl %ebx
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset ebx, 0
+ pushl %ecx
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset ecx, 0
+ pushl %edx
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset edx, 0
+
+ call __kernel_syscall
+ pushl %eax
+ .cfi_adjust_cfa_offset 4
+ .cfi_rel_offset eax, 0
+
+ mov 20(%esp), %ebx
+ mov 24(%esp), %ecx
+ mov 28(%esp), %edx
+ movl $__NR_getrandom, %eax
+ call *(%esp)
+ addl $4, %esp
+
+ cmpl $-MAX_ERRNO, %eax
+ jb 1f
+ negl %eax
+ pushl %eax
+ call __set_errno_internal
+ addl $4, %esp
+1:
+ popl %edx
+ popl %ecx
+ popl %ebx
+ ret
+END(getrandom)
diff --git a/libc/arch-x86_64/syscalls/getrandom.S b/libc/arch-x86_64/syscalls/getrandom.S
new file mode 100644
index 000000000..c5e44a966
--- /dev/null
+++ b/libc/arch-x86_64/syscalls/getrandom.S
@@ -0,0 +1,15 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(getrandom)
+ movl $__NR_getrandom, %eax
+ syscall
+ cmpq $-MAX_ERRNO, %rax
+ jb 1f
+ negl %eax
+ movl %eax, %edi
+ call __set_errno_internal
+1:
+ ret
+END(getrandom)
diff --git a/libc/include/sys/random.h b/libc/include/sys/random.h
new file mode 100644
index 000000000..34756520e
--- /dev/null
+++ b/libc/include/sys/random.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 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 _SYS_RANDOM_H_
+#define _SYS_RANDOM_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <linux/random.h>
+
+__BEGIN_DECLS
+
+/* See also arc4random_buf in <stdlib.h>, which is available in all API levels. */
+
+int getentropy(void* __buffer, size_t __buffer_size) __wur __INTRODUCED_IN_FUTURE;
+
+ssize_t getrandom(void* __buffer, size_t __buffer_size, unsigned int __flags) __wur __INTRODUCED_IN_FUTURE;
+
+__END_DECLS
+
+#endif
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 52698b6f0..f2b84f127 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1483,6 +1483,8 @@ LIBC_PRIVATE {
vfdprintf; # arm x86 mips nobrillo
wait3; # arm x86 mips nobrillo
wcswcs; # arm x86 mips nobrillo
+ getentropy; # future
+ getrandom; # future
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index db7368ded..284527c08 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1198,6 +1198,8 @@ LIBC_PRIVATE {
free_malloc_leak_info;
get_malloc_leak_info;
gMallocLeakZygoteChild;
+ getentropy; # future
+ getrandom; # future
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 0e41f6ccb..18354e218 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1509,6 +1509,8 @@ LIBC_PRIVATE {
vfdprintf; # arm x86 mips nobrillo
wait3; # arm x86 mips nobrillo
wcswcs; # arm x86 mips nobrillo
+ getentropy; # future
+ getrandom; # future
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 2e272f5ca..2aba50685 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1324,6 +1324,8 @@ LIBC_PRIVATE {
vfdprintf; # arm x86 mips nobrillo
wait3; # arm x86 mips nobrillo
wcswcs; # arm x86 mips nobrillo
+ getentropy; # future
+ getrandom; # future
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index db7368ded..284527c08 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1198,6 +1198,8 @@ LIBC_PRIVATE {
free_malloc_leak_info;
get_malloc_leak_info;
gMallocLeakZygoteChild;
+ getentropy; # future
+ getrandom; # future
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 6598e3d4b..c6282457e 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1323,6 +1323,8 @@ LIBC_PRIVATE {
vfdprintf; # arm x86 mips nobrillo
wait3; # arm x86 mips nobrillo
wcswcs; # arm x86 mips nobrillo
+ getentropy; # future
+ getrandom; # future
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index db7368ded..284527c08 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1198,6 +1198,8 @@ LIBC_PRIVATE {
free_malloc_leak_info;
get_malloc_leak_info;
gMallocLeakZygoteChild;
+ getentropy; # future
+ getrandom; # future
} LIBC_N;
LIBC_PLATFORM {
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index caea45a93..ed388144a 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -22,6 +22,11 @@
#include <sys/cdefs.h>
#include <stddef.h> // For size_t.
+// TODO: libandroid_support uses this file, so we need to wait for
+// <sys/random.h> to be in the NDK headers before we can lose this declaration.
+//#include <sys/random.h> // For getentropy.
+int getentropy(void*, size_t);
+
/* Redirect internal C library calls to the public function. */
#define _err err
#define _errx errx
@@ -65,9 +70,6 @@
*/
#define _PATH_TMP "/data/local/tmp/"
-/* We have OpenBSD's getentropy_linux.c, but we don't mention getentropy in any header. */
-__LIBC_HIDDEN__ extern int getentropy(void*, size_t);
-
/* OpenBSD has this as API, but we just use it internally. */
__LIBC_HIDDEN__ void* reallocarray(void*, size_t, size_t);
diff --git a/tests/sys_random_test.cpp b/tests/sys_random_test.cpp
new file mode 100644
index 000000000..a25490c67
--- /dev/null
+++ b/tests/sys_random_test.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// <sys/random.h> was only added as of glibc version 2.25.
+// Don't try to compile this code on older glibc versions.
+
+#include <sys/cdefs.h>
+#if defined(__BIONIC__)
+ #define HAVE_SYS_RANDOM 1
+#elif defined(__GLIBC_PREREQ)
+ #if __GLIBC_PREREQ(2, 25)
+ #define HAVE_SYS_RANDOM 1
+ #endif
+#endif
+
+
+#if defined(HAVE_SYS_RANDOM)
+#include <sys/random.h>
+#endif
+
+#include <errno.h>
+#include <gtest/gtest.h>
+
+TEST(sys_random, getentropy) {
+#if defined(HAVE_SYS_RANDOM)
+ char buf1[64];
+ char buf2[64];
+
+ ASSERT_EQ(0, getentropy(buf1, sizeof(buf1)));
+ ASSERT_EQ(0, getentropy(buf2, sizeof(buf2)));
+ ASSERT_TRUE(memcmp(buf1, buf2, sizeof(buf1)) != 0);
+#else
+ GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n";
+#endif
+}
+
+TEST(sys_random, getentropy_EFAULT) {
+#if defined(HAVE_SYS_RANDOM)
+ errno = 0;
+ ASSERT_EQ(-1, getentropy(nullptr, 1));
+ ASSERT_EQ(EFAULT, errno);
+#else
+ GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n";
+#endif
+}
+
+TEST(sys_random, getentropy_EIO) {
+#if defined(HAVE_SYS_RANDOM)
+ char buf[BUFSIZ];
+ static_assert(BUFSIZ > 256, "BUFSIZ <= 256!");
+
+ errno = 0;
+ ASSERT_EQ(-1, getentropy(buf, sizeof(buf)));
+ ASSERT_EQ(EIO, errno);
+#else
+ GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n";
+#endif
+}
+
+TEST(sys_random, getrandom) {
+#if defined(HAVE_SYS_RANDOM)
+ if (getrandom(nullptr, 0, 0) == -1 && errno == ENOSYS) {
+ GTEST_LOG_(INFO) << "This test requires a >= 3.17 kernel with getrandom(2).\n";
+ return;
+ }
+
+ char buf1[64];
+ char buf2[64];
+
+ ASSERT_EQ(64, getrandom(buf1, sizeof(buf1), 0));
+ ASSERT_EQ(64, getrandom(buf2, sizeof(buf2), 0));
+ ASSERT_TRUE(memcmp(buf1, buf2, sizeof(buf1)) != 0);
+#else
+ GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n";
+#endif
+}
+
+TEST(sys_random, getrandom_EFAULT) {
+#if defined(HAVE_SYS_RANDOM)
+ if (getrandom(nullptr, 0, 0) == -1 && errno == ENOSYS) {
+ GTEST_LOG_(INFO) << "This test requires a >= 3.17 kernel with getrandom(2).\n";
+ return;
+ }
+
+ errno = 0;
+ ASSERT_EQ(-1, getrandom(nullptr, 256, 0));
+ ASSERT_EQ(EFAULT, errno);
+#else
+ GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n";
+#endif
+}
+
+TEST(sys_random, getrandom_EINVAL) {
+#if defined(HAVE_SYS_RANDOM)
+ if (getrandom(nullptr, 0, 0) == -1 && errno == ENOSYS) {
+ GTEST_LOG_(INFO) << "This test requires a >= 3.17 kernel with getrandom(2).\n";
+ return;
+ }
+
+ errno = 0;
+ char buf[64];
+ ASSERT_EQ(-1, getrandom(buf, sizeof(buf), ~0));
+ ASSERT_EQ(EINVAL, errno);
+#else
+ GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n";
+#endif
+}