From 7ed0dd78fe4acb88ce74a12e1ca41738fcb0116a Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Tue, 11 Mar 2025 22:11:01 +0100 Subject: [PATCH 1/3] export arc4random_buf - 1.21.80.20 --- src/common.cpp | 12 ++++++++++++ src/common.h | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/src/common.cpp b/src/common.cpp index 52642c3..093009e 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -441,6 +441,13 @@ int shim::isnan(double d) { return std::isnan(d); } +#ifdef __linux__ +void shim::arc4random_buf(void* buf, size_t len) { + // We could use glibc arc4random_buf iff we would target glibc 2.36 + (void)syscall(SYS_getrandom, buf, len, 0); +} +#endif + void shim::add_common_shimmed_symbols(std::vector &list) { list.insert(list.end(), { {"__errno", bionic::get_errno}, @@ -631,6 +638,11 @@ void shim::add_time_shimmed_symbols(std::vector &list) { {"ctime_r", ::ctime_r}, {"tzname", ::tzname}, {"tzset", ::tzset}, +#ifdef __linux__ + {"arc4random_buf", shim::arc4random_buf}, +#else + {"arc4random_buf", ::arc4random_buf}, +#endif #ifndef __FreeBSD__ {"daylight", &::daylight}, #endif diff --git a/src/common.h b/src/common.h index 78d6fb7..1395329 100644 --- a/src/common.h +++ b/src/common.h @@ -151,6 +151,10 @@ namespace shim { int isnan(double d); +#ifdef __linux__ + void arc4random_buf(void* buf, size_t len); +#endif + int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags); void add_common_shimmed_symbols(std::vector &list); From 5e9ebae6fbd61c26474a82cedec80235243b1437 Mon Sep 17 00:00:00 2001 From: "Reed A. Cartwright" Date: Wed, 12 Mar 2025 11:00:18 -0700 Subject: [PATCH 2/3] Use ::arc4random_buf if it exists. Otherwise, shim it with std::random_device. --- src/common.cpp | 50 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/src/common.cpp b/src/common.cpp index 093009e..c622121 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -76,6 +76,18 @@ #include #include +#ifdef __linux__ +// glibc introduced arc4random_buf in 2.36 +#if defined(__GLIBC__) && !(__GLIBC__ < 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ < 36) +#define HAS_ARC4RANDOM_BUF 1 +#else +#include +#endif +#else +// OSX has arc4random_buf +#define HAS_ARC4RANDOM_BUF 1 +#endif + using namespace shim; void shim::handle_runtime_error(const char *fmt, ...) { @@ -275,10 +287,6 @@ int shim::prctl(bionic::prctl_num opt, unsigned long a2, unsigned long a3, unsig #endif } -uint32_t shim::arc4random() { - return 0; // TODO: -} - void* shim::__memcpy_chk(void *dst, const void *src, size_t size, size_t max_len) { if (size > max_len) { fprintf(stderr, "detected copy past buffer size"); @@ -410,7 +418,7 @@ ssize_t shim::getrandom(void *buf, size_t len, unsigned int flags) { #else // TODO do we need look at flags? // Should work for bsd and macOS - arc4random_buf(buf, len); + ::arc4random_buf(buf, len); return (ssize_t)len; #endif } @@ -441,10 +449,27 @@ int shim::isnan(double d) { return std::isnan(d); } -#ifdef __linux__ +#ifndef HAS_ARC4RANDOM_BUF void shim::arc4random_buf(void* buf, size_t len) { - // We could use glibc arc4random_buf iff we would target glibc 2.36 - (void)syscall(SYS_getrandom, buf, len, 0); + // Using SYS_getrandom is a bit complex since it can be interrupted + // or not supported. Even if we used SYS_getrandom, we would have to + // fall back to an alternative strategy or error out if it failed. + // Instead rely on std::random_device to fill buf, allowing + // std::random_device to handle the complex stuff. + std::random_device get_rand; + while(len > 0) { + unsigned int u = get_rand(); + size_t n = std::min(len, sizeof(unsigned int)); + ::memcpy(buf, &u, n); + buf = (uint8_t*)buf + n; + len -= n; + } +} + +uint32_t shim::arc4random() { + uint32_t u; + shim::arc4random_buf(&u, sizeof(u)); + return u; } #endif @@ -638,7 +663,7 @@ void shim::add_time_shimmed_symbols(std::vector &list) { {"ctime_r", ::ctime_r}, {"tzname", ::tzname}, {"tzset", ::tzset}, -#ifdef __linux__ +#ifndef HAS_ARC4RANDOM_BUF {"arc4random_buf", shim::arc4random_buf}, #else {"arc4random_buf", ::arc4random_buf}, @@ -992,8 +1017,11 @@ void shim::add_misc_shimmed_symbols(std::vector &list) { {"openlog", openlog}, {"closelog", closelog}, {"syslog", syslog}, - - {"arc4random", arc4random}, +#ifndef HAS_ARC4RANDOM_BUF + {"arc4random", shim::arc4random}, +#else + {"arc4random", ::arc4random}, +#endif }); } From d7489a34bc2eb0d1776477b56d2f9946a38a03a3 Mon Sep 17 00:00:00 2001 From: "Reed A. Cartwright" Date: Wed, 12 Mar 2025 11:19:35 -0700 Subject: [PATCH 3/3] Always define shim::arc4random* even if it isn't used. --- src/common.cpp | 6 ++++-- src/common.h | 6 ++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/common.cpp b/src/common.cpp index c622121..670f1c0 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -449,8 +449,10 @@ int shim::isnan(double d) { return std::isnan(d); } -#ifndef HAS_ARC4RANDOM_BUF void shim::arc4random_buf(void* buf, size_t len) { +#ifdef HAS_ARC4RANDOM_BUF + ::arc4random_buf(buf, len); +#else // Using SYS_getrandom is a bit complex since it can be interrupted // or not supported. Even if we used SYS_getrandom, we would have to // fall back to an alternative strategy or error out if it failed. @@ -464,6 +466,7 @@ void shim::arc4random_buf(void* buf, size_t len) { buf = (uint8_t*)buf + n; len -= n; } +#endif } uint32_t shim::arc4random() { @@ -471,7 +474,6 @@ uint32_t shim::arc4random() { shim::arc4random_buf(&u, sizeof(u)); return u; } -#endif void shim::add_common_shimmed_symbols(std::vector &list) { list.insert(list.end(), { diff --git a/src/common.h b/src/common.h index 1395329..05d7f55 100644 --- a/src/common.h +++ b/src/common.h @@ -101,8 +101,6 @@ namespace shim { int sendfile(int src, int dst, bionic::off_t *offset, size_t count); - uint32_t arc4random(); - void *__memcpy_chk(void *dst, const void *src, size_t size, size_t max_len); void *__memmove_chk(void *dst, const void *src, size_t size, size_t max_len); @@ -151,9 +149,9 @@ namespace shim { int isnan(double d); -#ifdef __linux__ void arc4random_buf(void* buf, size_t len); -#endif + + uint32_t arc4random(); int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags);