prim.c: add /dev/urandom fallback for old OS X

arc4random_buf is not always available. Also changed MAC_OS_X_VERSION_MAX_ALLOWED check to MAC_OS_X_VERSION_MIN_REQUIRED, because no runtime checking of either the OS version or the presence of weak-linked symbols is being done, so runtime behaviour would be incorrect if you built against the latest SDK and deployed to an older OS version.
This commit is contained in:
Joshua Root 2023-11-28 09:26:01 +11:00 committed by GitHub
parent 4e50d6714d
commit de4453ecf5
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS.
GPG key ID: 4AEE18F83AFDEB23

View file

@ -735,16 +735,40 @@ bool _mi_prim_getenv(const char* name, char* result, size_t result_size) {
#if defined(MAC_OS_X_VERSION_10_10) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10
#include <CommonCrypto/CommonCryptoError.h>
#include <CommonCrypto/CommonRandom.h>
#elif MAC_OS_X_VERSION_MIN_REQUIRED < 1070
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#endif
bool _mi_prim_random_buf(void* buf, size_t buf_len) {
#if defined(MAC_OS_X_VERSION_10_15) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15
#if defined(MAC_OS_X_VERSION_10_15) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_15
// We prefere CCRandomGenerateBytes as it returns an error code while arc4random_buf
// may fail silently on macOS. See PR #390, and <https://opensource.apple.com/source/Libc/Libc-1439.40.11/gen/FreeBSD/arc4random.c.auto.html>
return (CCRandomGenerateBytes(buf, buf_len) == kCCSuccess);
#else
#elif MAC_OS_X_VERSION_MIN_REQUIRED >= 1070
// fall back on older macOS
arc4random_buf(buf, buf_len);
return true;
#else
// fall back on even older old Mac OS X
int flags = O_RDONLY;
#if defined(O_CLOEXEC)
flags |= O_CLOEXEC;
#endif
int fd = mi_prim_open("/dev/urandom", flags);
if (fd < 0) return false;
size_t count = 0;
while(count < buf_len) {
ssize_t ret = mi_prim_read(fd, (char*)buf + count, buf_len - count);
if (ret<=0) {
if (errno!=EAGAIN && errno!=EINTR) break;
}
else {
count += ret;
}
}
mi_prim_close(fd);
return (count==buf_len);
#endif
}