Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion .github/workflows/cross-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
sudo apt-get -y install qemu-user qemu-user-binfmt
- uses: actions/checkout@v6
- name: PPC64LE Build/Test
run: tests/ci/run_cross_tests.sh ppc64le powerpc64le-unknown-linux-gnu "-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_BUILD_TYPE=Release -DFIPS=1 -DBUILD_SHARED_LIBS=1"
run: tests/ci/run_cross_tests.sh ppc64le powerpc64le-unknown-linux-gnu "-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_BUILD_TYPE=Release -DFIPS=1 -DBUILD_SHARED_LIBS=1" "-DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS=-DOPENSSL_GETAUXVAL_FORCE_PROC_FALLBACK"
riscv64-non-fips-build-test:
if: github.repository_owner == 'aws'
runs-on: ubuntu-24.04
Expand Down Expand Up @@ -84,6 +84,35 @@ jobs:
- uses: actions/checkout@v6
- name: armv6 Build/Test
run: tests/ci/run_cross_tests.sh armv6 armv6-unknown-linux-gnueabi "-DCMAKE_BUILD_TYPE=Release"
armv7-uclibc-build-test:
# Bootlin 2022.08-1 ships uclibc-ng 1.0.42, which predates uclibc-ng's
# own <sys/auxv.h> (added in 1.0.43). On this sysroot,
# __has_include(<sys/auxv.h>) in cpu_getauxval_linux.h evaluates false,
# so natural detection lands on the /proc/self/auxv fallback -- exactly
# the scenario from https://github.com/aws/aws-lc/issues/3188. A single
# job thus covers both the non-glibc detection path and the fallback
# code path end-to-end. If this toolchain is ever bumped to a release
# that does ship <sys/auxv.h>, the "INFO:" line in
# run_cross_tests_bootlin.sh will make the coverage loss visible in the
# CI log.
if: github.repository_owner == 'aws'
runs-on: ubuntu-24.04
steps:
- name: Install qemu
run: |
sudo apt-get update -o Acquire::Languages=none -o Acquire::Translation=none
sudo apt-get -y install qemu-user qemu-user-binfmt
Comment thread
justsmth marked this conversation as resolved.
- uses: actions/checkout@v6
- name: armv7 uclibc Build/Test
run: |
tests/ci/run_cross_tests_bootlin.sh \
armv7 \
armv7-eabihf--uclibc--stable-2022.08-1 \
arm-buildroot-linux-uclibcgnueabihf \
tar.bz2 \
9e4191ab996fdf5f4e8de7e4617c67cbf46127ca2754fca0ad45d60e393ace05 \
arm \
"-DCMAKE_BUILD_TYPE=Release"
loongarch64-non-fips-build-test:
runs-on: ubuntu-24.04
steps:
Expand Down
6 changes: 6 additions & 0 deletions SANDBOXING.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ On Linux ARM platforms, BoringSSL depends on OS APIs to query CPU capabilities.
work around bugs in older Android devices, may additionally read
`/proc/cpuinfo`.

On Linux targets whose libc does not provide `getauxval` (e.g. older uclibc),
AWS-LC falls back to reading `/proc/self/auxv` directly. This applies to the
ARM, AArch64, and PPC64LE CPU capability paths as well as the `urandom`
entropy path's debug lookup. Sandbox policies should permit opening
`/proc/self/auxv` on such targets.

On 64-bit Apple ARM platforms, BoringSSL needs to query `hw.optional.*` sysctls.

If querying CPU capabilities fails, BoringSSL will still function, but may not
Expand Down
2 changes: 1 addition & 1 deletion crypto/fipsmodule/cpucap/cpu_aarch64_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#if defined(OPENSSL_AARCH64) && defined(OPENSSL_LINUX) && \
!defined(OPENSSL_STATIC_ARMCAP)

#include <sys/auxv.h>
#include "cpu_getauxval_linux.h"

#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
Expand Down
2 changes: 1 addition & 1 deletion crypto/fipsmodule/cpucap/cpu_arm_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
!defined(OPENSSL_STATIC_ARMCAP)
#include <errno.h>
#include <fcntl.h>
#include <sys/auxv.h>
#include <sys/types.h>
#include <unistd.h>

#include <openssl/arm_arch.h>
#include <openssl/mem.h>

#include "cpu_arm_linux.h"
#include "cpu_getauxval_linux.h"

static int open_eintr(const char *path, int flags) {
int ret;
Expand Down
137 changes: 137 additions & 0 deletions crypto/fipsmodule/cpucap/cpu_getauxval_linux.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR ISC

#ifndef OPENSSL_HEADER_CRYPTO_CPUCAP_GETAUXVAL_LINUX_H
#define OPENSSL_HEADER_CRYPTO_CPUCAP_GETAUXVAL_LINUX_H

#include <openssl/base.h>

// This header provides a unified interface for obtaining auxiliary vector
// values on Linux. When the system provides getauxval (glibc >= 2.16, musl,
// recent uclibc-ng), it is used directly via <sys/auxv.h>. Otherwise, a
// fallback reads /proc/self/auxv.
//
// After including this header (on Linux), OPENSSL_HAS_GETAUXVAL is defined
// and getauxval(type) is callable -- regardless of whether <sys/auxv.h> was
// available -- so call sites do not need to special-case the libc.

#if defined(OPENSSL_LINUX)

// Detect <sys/auxv.h> availability. Use __has_include as the primary
// mechanism since it directly answers the question. Fall back to
// library-specific heuristics for compilers that lack __has_include.
//
// Define OPENSSL_GETAUXVAL_FORCE_PROC_FALLBACK to skip detection and
// unconditionally use the /proc/self/auxv fallback. This is used in CI to
// exercise the fallback path on systems that do have <sys/auxv.h>.
#if !defined(OPENSSL_HAS_GETAUXVAL) && !defined(OPENSSL_GETAUXVAL_FORCE_PROC_FALLBACK)
#if defined(__has_include)
#if __has_include(<sys/auxv.h>)
#define OPENSSL_HAS_GETAUXVAL
#endif
#elif defined(__GLIBC_PREREQ)
#if __GLIBC_PREREQ(2, 16)
#define OPENSSL_HAS_GETAUXVAL
#endif
#elif !defined(__UCLIBC__)
// Non-glibc, non-uclibc libc (e.g. musl) — assume getauxval is available.
#define OPENSSL_HAS_GETAUXVAL
#endif
#endif // !defined(OPENSSL_HAS_GETAUXVAL) && !defined(OPENSSL_GETAUXVAL_FORCE_PROC_FALLBACK)

#if defined(OPENSSL_HAS_GETAUXVAL)
#include <sys/auxv.h>
#else

// When <sys/auxv.h> is not available (e.g. older uclibc without getauxval),
// fall back to reading /proc/self/auxv. The file contains sequential pairs of
// unsigned long values: [type_0, value_0, type_1, value_1, ..., AT_NULL, 0].

#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

// Auxiliary vector type constants from the Linux kernel ABI
// (include/uapi/linux/auxvec.h). The specific values used here are stable.
#if !defined(AT_NULL)
#define AT_NULL 0
#endif
#if !defined(AT_HWCAP)
#define AT_HWCAP 16
#endif
#if !defined(AT_HWCAP2)
#define AT_HWCAP2 26
#endif
#if !defined(AT_EXECFN)
#define AT_EXECFN 31
#endif

// getauxval returns the value of the auxiliary-vector entry of the given
// |type|, or 0 if no such entry exists or /proc/self/auxv is unavailable.
//
// Note: unlike glibc >= 2.19, this implementation does not set errno to
// ENOENT when |type| is not present. No caller in AWS-LC inspects errno
// after getauxval, so this difference is not observable.
//
// OPENSSL_UNUSED guards against -Wunused-function in translation units that
// include this header but do not call getauxval (none today, but cheap
// insurance against future refactors).
static OPENSSL_UNUSED unsigned long getauxval(unsigned long type) {
Comment thread
justsmth marked this conversation as resolved.
const int saved_errno = errno;
int fd;
do {
fd = open("/proc/self/auxv", O_RDONLY | O_CLOEXEC);
} while (fd < 0 && errno == EINTR);
if (fd < 0) {
errno = saved_errno;
return 0;
}

unsigned long result = 0;
unsigned long pair[2];
// Bound the loop defensively. Real auxv vectors have on the order of 30
// entries; 128 is a comfortable upper bound that guarantees forward
// progress even if /proc/self/auxv is malformed or missing its AT_NULL
// terminator.
for (int i = 0; i < 128; i++) {
// read() on /proc/self/auxv may in principle return a short count; loop
// until a full pair is read or we hit EOF/error.
size_t filled = 0;
while (filled < sizeof(pair)) {
ssize_t n = read(fd, (char *)pair + filled, sizeof(pair) - filled);
if (n > 0) {
filled += (size_t)n;
} else if (n < 0 && errno == EINTR) {
continue;
} else {
// EOF or unrecoverable error. Whatever we've accumulated so far is
// unusable; treat the lookup as "not found".
goto done;
}
}
if (pair[0] == AT_NULL) {
// AT_NULL terminates the vector.
break;
}
if (pair[0] == type) {
result = pair[1];
break;
}
}

done:
close(fd);
errno = saved_errno;
return result;
}

// Expose OPENSSL_HAS_GETAUXVAL so that callers can uniformly gate on
// "getauxval is callable" without caring whether it came from the libc or
// the fallback above.
#define OPENSSL_HAS_GETAUXVAL

#endif // OPENSSL_HAS_GETAUXVAL

#endif // OPENSSL_LINUX

#endif // OPENSSL_HEADER_CRYPTO_CPUCAP_GETAUXVAL_LINUX_H
14 changes: 9 additions & 5 deletions crypto/fipsmodule/cpucap/cpu_ppc64le.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@

#if defined(OPENSSL_PPC64LE)

// On Linux, use the shared getauxval helper (which falls back to reading
// /proc/self/auxv when <sys/auxv.h> is unavailable). On FreeBSD, use the
// system-provided <sys/auxv.h>/elf_aux_info. On other platforms no
// auxv-style API is available; OPENSSL_ppc64le_hwcap2 stays zero-initialized.
#if defined(OPENSSL_LINUX)
#include "cpu_getauxval_linux.h"
#elif defined(OPENSSL_FREEBSD)
#include <sys/auxv.h>
#endif

#if !defined(PPC_FEATURE2_HAS_VCRYPTO)
// PPC_FEATURE2_HAS_VCRYPTO was taken from section 4.1.2.3 of the “OpenPOWER
Expand Down Expand Up @@ -57,14 +65,10 @@ static void handle_cpu_env(unsigned long *out, const char *in) {
extern uint8_t OPENSSL_cpucap_initialized;

void OPENSSL_cpuid_setup(void) {
#if defined(AT_HWCAP2)
#if defined(OPENSSL_LINUX)
Comment thread
justsmth marked this conversation as resolved.
OPENSSL_ppc64le_hwcap2 = getauxval(AT_HWCAP2);
#elif defined(OPENSSL_FREEBSD)
#elif defined(OPENSSL_FREEBSD) && defined(AT_HWCAP2)
elf_aux_info(AT_HWCAP2, &OPENSSL_ppc64le_hwcap2, sizeof(OPENSSL_ppc64le_hwcap2));
#else
OPENSSL_ppc64le_hwcap2 = 0;
#endif
#endif
OPENSSL_cpucap_initialized = 1;

Expand Down
19 changes: 5 additions & 14 deletions crypto/rand_extra/urandom.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,12 @@
#include <sys/system_properties.h>
#endif

// On non-Android Linux, delegate getauxval availability detection (including
// the /proc/self/auxv fallback for libcs that lack <sys/auxv.h>, such as older
// uclibc) to the shared helper. Android intentionally skips the AT_EXECFN
// debug lookup to avoid depending on getauxval in older NDK sysroots.
#if !defined(OPENSSL_ANDROID)
#define OPENSSL_HAS_GETAUXVAL
#endif
// glibc prior to 2.16 does not have getauxval and sys/auxv.h. Android has some
// host builds (i.e. not building for Android itself, so |OPENSSL_ANDROID| is
// unset) which are still using a 2.15 sysroot.
//
// TODO(davidben): Remove this once Android updates their sysroot.
#if defined(__GLIBC_PREREQ)
#if !__GLIBC_PREREQ(2, 16)
#undef OPENSSL_HAS_GETAUXVAL
#endif
#endif
#if defined(OPENSSL_HAS_GETAUXVAL)
#include <sys/auxv.h>
#include "../fipsmodule/cpucap/cpu_getauxval_linux.h"
#endif
#endif // OPENSSL_LINUX

Expand Down
Loading
Loading