Require getauxval on 32-bit Arm Linux
We used to have a tower of fallbacks to support older Androids that were
missing getauxval. The comments say getauxval is available in Android
API level 20 or higher, but this wasn't right. It's actually API level
18 or higher per the NDK headers and
https://developer.android.com/ndk/guides/cpu-features
Android API level 18 is Android 4.3, or Jelly Bean MR2. Recent versions
of the NDK (starting r24, March 2022) don't even support Jelly Bean,
i.e. the minimum API level is 19, and the usage statistics in the latest
Android Studio stop at KitKat. As far as I know, nothing needs us to
support API levels 17 and below anymore.
Update-Note: BoringSSL now requires API level 18 or later. Projects
needing to support API level of 17 or below will fail to build due to
the use of getauxval. If any such projects exist, please contact
BoringSSL maintainers.
Change-Id: Iedc4836ffd701428ab6d11253d4ebd5a9121e667
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/57506
Reviewed-by: Bob Beck <bbe@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/cpu_arm_linux.c b/crypto/cpu_arm_linux.c
index 25b50f6..d13ac21 100644
--- a/crypto/cpu_arm_linux.c
+++ b/crypto/cpu_arm_linux.c
@@ -18,6 +18,7 @@
!defined(OPENSSL_STATIC_ARMCAP)
#include <errno.h>
#include <fcntl.h>
+#include <sys/auxv.h>
#include <sys/types.h>
#include <unistd.h>
@@ -26,13 +27,6 @@
#include "cpu_arm_linux.h"
-#define AT_HWCAP 16
-#define AT_HWCAP2 26
-
-// |getauxval| is not available on Android until API level 20. Link it as a weak
-// symbol and use other methods as fallback.
-unsigned long getauxval(unsigned long type) __attribute__((weak));
-
static int open_eintr(const char *path, int flags) {
int ret;
do {
@@ -49,21 +43,6 @@
return ret;
}
-// read_full reads exactly |len| bytes from |fd| to |out|. On error or end of
-// file, it returns zero.
-static int read_full(int fd, void *out, size_t len) {
- char *outp = out;
- while (len > 0) {
- ssize_t ret = read_eintr(fd, outp, len);
- if (ret <= 0) {
- return 0;
- }
- outp += ret;
- len -= ret;
- }
- return 1;
-}
-
// read_file opens |path| and reads until end-of-file. On success, it returns
// one and sets |*out_ptr| and |*out_len| to a newly-allocated buffer with the
// contents. Otherwise, it returns zero.
@@ -116,32 +95,6 @@
return ret;
}
-// getauxval_proc behaves like |getauxval| but reads from /proc/self/auxv.
-static unsigned long getauxval_proc(unsigned long type) {
- int fd = open_eintr("/proc/self/auxv", O_RDONLY);
- if (fd < 0) {
- return 0;
- }
-
- struct {
- unsigned long tag;
- unsigned long value;
- } entry;
-
- for (;;) {
- if (!read_full(fd, &entry, sizeof(entry)) ||
- (entry.tag == 0 && entry.value == 0)) {
- break;
- }
- if (entry.tag == type) {
- close(fd);
- return entry.value;
- }
- }
- close(fd);
- return 0;
-}
-
extern uint32_t OPENSSL_armcap_P;
static int g_needs_hwcap2_workaround;
@@ -157,25 +110,8 @@
cpuinfo.data = cpuinfo_data;
cpuinfo.len = cpuinfo_len;
- // |getauxval| is not available on Android until API level 20. If it is
- // unavailable, read from /proc/self/auxv as a fallback. This is unreadable
- // on some versions of Android, so further fall back to /proc/cpuinfo.
- //
- // See
- // https://android.googlesource.com/platform/ndk/+/882ac8f3392858991a0e1af33b4b7387ec856bd2
- // and b/13679666 (Google-internal) for details.
- unsigned long hwcap = 0;
- if (getauxval != NULL) {
- hwcap = getauxval(AT_HWCAP);
- }
- if (hwcap == 0) {
- hwcap = getauxval_proc(AT_HWCAP);
- }
- if (hwcap == 0) {
- hwcap = crypto_get_arm_hwcap_from_cpuinfo(&cpuinfo);
- }
-
// Matching OpenSSL, only report other features if NEON is present.
+ unsigned long hwcap = getauxval(AT_HWCAP);
if (hwcap & HWCAP_NEON) {
OPENSSL_armcap_P |= ARMV7_NEON;
@@ -184,10 +120,7 @@
// this is now rare (see Chrome's Net.NeedsHWCAP2Workaround metric), but AES
// and PMULL extensions are very useful, so we still carry the workaround
// for now.
- unsigned long hwcap2 = 0;
- if (getauxval != NULL) {
- hwcap2 = getauxval(AT_HWCAP2);
- }
+ unsigned long hwcap2 = getauxval(AT_HWCAP2);
if (hwcap2 == 0) {
hwcap2 = crypto_get_arm_hwcap2_from_cpuinfo(&cpuinfo);
g_needs_hwcap2_workaround = hwcap2 != 0;