Skip to content
Open
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
41 changes: 38 additions & 3 deletions Source/WTF/wtf/RandomDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@
#include <unistd.h>
#endif

#if OS(LINUX)
#include <sys/syscall.h>
#if defined(SYS_getrandom)
#define RANDOM_DEVICE_USE_GETRANDOM 1
#ifndef GRND_NONBLOCK
#define GRND_NONBLOCK 0x0001
#endif
#endif
#endif
#ifndef RANDOM_DEVICE_USE_GETRANDOM
#define RANDOM_DEVICE_USE_GETRANDOM 0
#endif

#if OS(WINDOWS)
#include <windows.h>
#include <wincrypt.h> // windows.h must be included before wincrypt.h.
Expand Down Expand Up @@ -66,9 +79,24 @@ NEVER_INLINE NO_RETURN_DUE_TO_CRASH static void crashUnableToReadFromURandom()
#if !OS(DARWIN) && !OS(FUCHSIA) && !OS(WINDOWS)
RandomDevice::RandomDevice()
{
#if RANDOM_DEVICE_USE_GETRANDOM
// Prefer getrandom(2): same kernel pool as /dev/urandom, but needs no
// filesystem access and keeps no fd open. Probe once with GRND_NONBLOCK; if
// the pool is already initialized use getrandom from here on (it can never
// become uninitialized again). Otherwise -- EAGAIN (pool not ready, where
// /dev/urandom would return without blocking), ENOSYS (pre-3.17 kernel) or
// EPERM (seccomp) -- keep the historical /dev/urandom behaviour.
uint8_t probe;
long probeResult;
do {
probeResult = syscall(SYS_getrandom, &probe, sizeof(probe), GRND_NONBLOCK);
} while (probeResult == -1 && errno == EINTR);
if (probeResult == 1)
return; // m_fd stays -1: cryptographicallyRandomValues() uses getrandom.
#endif
int ret = 0;
do {
ret = open("/dev/urandom", O_RDONLY, 0);
ret = open("/dev/urandom", O_RDONLY | O_CLOEXEC, 0);
} while (ret == -1 && errno == EINTR);
m_fd = ret;
if (m_fd < 0)
Expand All @@ -79,7 +107,8 @@ RandomDevice::RandomDevice()
#if !OS(DARWIN) && !OS(FUCHSIA) && !OS(WINDOWS)
RandomDevice::~RandomDevice()
{
close(m_fd);
if (m_fd >= 0)
close(m_fd);
}
#endif

Expand All @@ -94,8 +123,14 @@ void RandomDevice::cryptographicallyRandomValues(std::span<uint8_t> buffer)
#elif OS(UNIX)
ssize_t amountRead = 0;
while (static_cast<size_t>(amountRead) < buffer.size()) {
ssize_t currentRead;
WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN
ssize_t currentRead = read(m_fd, buffer.data() + amountRead, buffer.size() - amountRead);
#if RANDOM_DEVICE_USE_GETRANDOM
if (m_fd < 0)
currentRead = syscall(SYS_getrandom, buffer.data() + amountRead, buffer.size() - amountRead, 0);
else
#endif
currentRead = read(m_fd, buffer.data() + amountRead, buffer.size() - amountRead);
WTF_ALLOW_UNSAFE_BUFFER_USAGE_END
// We need to check for both EAGAIN and EINTR since on some systems /dev/urandom
// is blocking and on others it is non-blocking.
Expand Down
32 changes: 23 additions & 9 deletions Source/WTF/wtf/linux/CurrentProcessMemoryStatus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,43 @@
#include "config.h"
#include <wtf/linux/CurrentProcessMemoryStatus.h>

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <mutex>
#include <stdlib.h>
#include <unistd.h>
#include <wtf/PageBlock.h>

namespace WTF {

IGNORE_CLANG_WARNINGS_BEGIN("unsafe-buffer-usage-in-libc-call")
WTF_ALLOW_UNSAFE_BUFFER_USAGE_BEGIN
void currentProcessMemoryStatus(ProcessMemoryStatus& memoryStatus)
{
FILE* file = fopen("/proc/self/statm", "r");
if (!file)
// This is on the GC's heap-growth path (Heap::proportionalHeapSize via
// memoryFootprint()), so open /proc/self/statm once and pread() it rather
// than fopen/fclose on every call. If it can't be opened, latch to "no data".
static int statmFd = -1;
static std::once_flag onceFlag;
std::call_once(onceFlag, [] {
do {
statmFd = open("/proc/self/statm", O_RDONLY | O_CLOEXEC);
} while (statmFd == -1 && errno == EINTR);
});
if (statmFd < 0)
return;

char buffer[128];
char* line = fgets(buffer, 128, file);
fclose(file);
if (!line)
ssize_t length;
do {
length = pread(statmFd, buffer, sizeof(buffer) - 1, 0);
} while (length == -1 && errno == EINTR);
if (length <= 0)
return;
buffer[length] = '\0';

size_t pageSize = WTF::pageSize();
char* end = nullptr;
unsigned long long intValue = strtoull(line, &end, 10);
unsigned long long intValue = strtoull(buffer, &end, 10);
memoryStatus.size = intValue * pageSize;
intValue = strtoull(end, &end, 10);
memoryStatus.resident = intValue * pageSize;
Expand All @@ -63,6 +77,6 @@ void currentProcessMemoryStatus(ProcessMemoryStatus& memoryStatus)
intValue = strtoull(end, &end, 10);
memoryStatus.dt = intValue * pageSize;
}
IGNORE_CLANG_WARNINGS_END
WTF_ALLOW_UNSAFE_BUFFER_USAGE_END

} // namespace WTF
40 changes: 37 additions & 3 deletions Source/bmalloc/bmalloc/CryptoRandom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@
#include <unistd.h>
#endif

#if BOS(LINUX)
#include <sys/syscall.h>
#if defined(SYS_getrandom)
#define CRYPTO_RANDOM_USE_GETRANDOM 1
#ifndef GRND_NONBLOCK
#define GRND_NONBLOCK 0x0001
#endif
#endif
#endif
#ifndef CRYPTO_RANDOM_USE_GETRANDOM
#define CRYPTO_RANDOM_USE_GETRANDOM 0
#endif

#if BOS(DARWIN)
#include <CommonCrypto/CommonCryptoError.h>
#include <CommonCrypto/CommonRandom.h>
Expand Down Expand Up @@ -118,20 +131,41 @@ void ARC4RandomNumberGenerator::stir()
BCRASH();
#else
static std::once_flag onceFlag;
static int fd;
static int fd = -1;
std::call_once(
onceFlag,
[] {
#if CRYPTO_RANDOM_USE_GETRANDOM
// Prefer getrandom(2): same kernel pool as /dev/urandom, but needs no
// filesystem access and keeps no fd open. Probe once with GRND_NONBLOCK;
// if the pool is already initialized use getrandom from here on (it can
// never become uninitialized again). Otherwise -- EAGAIN (pool not ready,
// where /dev/urandom would return without blocking), ENOSYS (pre-3.17
// kernel) or EPERM (seccomp) -- keep the historical /dev/urandom behaviour.
uint8_t probe;
long probeResult;
do {
probeResult = syscall(SYS_getrandom, &probe, sizeof(probe), GRND_NONBLOCK);
} while (probeResult == -1 && errno == EINTR);
if (probeResult == 1)
return; // fd stays -1: use getrandom below.
#endif
int ret = 0;
do {
ret = open("/dev/urandom", O_RDONLY, 0);
ret = open("/dev/urandom", O_RDONLY | O_CLOEXEC, 0);
} while (ret == -1 && errno == EINTR);
RELEASE_BASSERT(ret >= 0);
fd = ret;
});
ssize_t amountRead = 0;
while (static_cast<size_t>(amountRead) < length) {
ssize_t currentRead = read(fd, randomness + amountRead, length - amountRead);
ssize_t currentRead;
#if CRYPTO_RANDOM_USE_GETRANDOM
if (fd < 0)
currentRead = syscall(SYS_getrandom, randomness + amountRead, length - amountRead, 0);
else
#endif
currentRead = read(fd, randomness + amountRead, length - amountRead);
// We need to check for both EAGAIN and EINTR since on some systems /dev/urandom
// is blocking and on others it is non-blocking.
if (currentRead == -1)
Expand Down
Loading