mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-29 04:01:27 +01:00
ELFCodeLoader: Don't use std::random_device for RNG
Fixes #2095 std::random_device can fail to find a random source and throw an assert during initialization. The constructor allows you to provide a token string to select an explicit random source, but this is c++ library specific and will still assert if the source isn't found. Also specific tokens are very much target and library specific, so it is unsafe to use. In the libstdc++ case, the default implementation will try to open `/dev/urandom` which might not be available on all targets. Instead of relying on this C++ object, use the `getrandom` syscall directly to generate our RNG used in the ELFCodeLoader. Resolves any sort of asserting case, blocks on RNG generation, and is guaranteed to be available since this syscall has been available since a very old kernel version.
This commit is contained in:
1 parent
1521e0a248
commit
fcddf86352
1 file changed
+24
-8
@@ -34,6 +34,7 @@
|
||||
#include <sys/auxv.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/personality.h>
|
||||
#include <sys/random.h>
|
||||
|
||||
#define PAGE_START(x) ((x) & ~(uintptr_t)(4095))
|
||||
#define PAGE_OFFSET(x) ((x) & 4095)
|
||||
@@ -176,6 +177,17 @@ class ELFCodeLoader2 final : public FEXCore::CodeLoader {
|
||||
return LoadBase;
|
||||
}
|
||||
|
||||
static bool GetRandom(void *Data, size_t DataSize) {
|
||||
ssize_t Result{};
|
||||
do {
|
||||
// This is guaranteed to not be interrupted by a signal,
|
||||
// since fewer than 256 bytes of RNG data are requested
|
||||
Result = getrandom(Data, DataSize, 0);
|
||||
} while (Result != -1 && Result != DataSize);
|
||||
|
||||
return Result != -1;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static std::string ResolveRootfsFile(std::string const &File, std::string RootFS) {
|
||||
@@ -472,9 +484,12 @@ class ELFCodeLoader2 final : public FEXCore::CodeLoader {
|
||||
if (!NoRandomize) {
|
||||
constexpr uint64_t ASLR_BITS_64 = 28;
|
||||
constexpr uint64_t ASLR_BITS_32 = 8;
|
||||
std::random_device rd;
|
||||
std::uniform_int_distribution<uint64_t> d(0);
|
||||
uint64_t ASLR_Offset = d(rd);
|
||||
uint64_t ASLR_Offset{};
|
||||
if (!GetRandom(&ASLR_Offset, sizeof(ASLR_Offset))) {
|
||||
// getrandom failed for some reason.
|
||||
ASLR_Offset = 0;
|
||||
LogMan::Msg::EFmt("RNG failed. ASLR will not work.");
|
||||
}
|
||||
|
||||
if (Is64BitMode()) {
|
||||
ASLR_Offset &= (1ULL << ASLR_BITS_64) - 1;
|
||||
@@ -720,11 +735,12 @@ class ELFCodeLoader2 final : public FEXCore::CodeLoader {
|
||||
}
|
||||
else {
|
||||
// Nothing provided from the kernel, generate our own random values.
|
||||
std::random_device rd;
|
||||
std::uniform_int_distribution<uint64_t> d(0);
|
||||
|
||||
RandomLoc[0] = d(rd);
|
||||
RandomLoc[1] = d(rd);
|
||||
if (!GetRandom(&RandomLoc[0], sizeof(uint64_t) * 2)) {
|
||||
// getrandom failed for some reason.
|
||||
RandomLoc[0] = 0;
|
||||
RandomLoc[1] = 0;
|
||||
LogMan::Msg::EFmt("RNG failed. AT_RANDOM will not be random.");
|
||||
}
|
||||
}
|
||||
|
||||
// Stack setup
|
||||
|
||||
Reference in new issue
Block a user