Merge pull request #3946 from Sonicadvance1/vdso_getrandom

VDSO: Implements v6.11 vdso getrandom
This commit is contained in:
LC 2024-09-28 15:26:35 -04:00 committed by GitHub
commit e902ad5278
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 82 additions and 6 deletions

View File

@ -566,7 +566,7 @@ int main(int argc, char** argv, char** const envp) {
ThunkHandler->RegisterTLSState(ParentThread);
// Pass in our VDSO thunks
ThunkHandler->AppendThunkDefinitions(FEX::VDSO::GetVDSOThunkDefinitions());
ThunkHandler->AppendThunkDefinitions(FEX::VDSO::GetVDSOThunkDefinitions(Loader.Is64BitMode()));
SignalDelegation->SetVDSOSigReturn();
SyscallHandler->DeserializeSeccompFD(ParentThread, FEXSeccompFD);

View File

@ -28,12 +28,14 @@ namespace VDSOHandlers {
using ClockGetTimeType = decltype(::clock_gettime)*;
using ClockGetResType = decltype(::clock_getres)*;
using GetCPUType = decltype(FHU::Syscalls::getcpu)*;
using GetRandomType = ssize_t (*)(void*, size_t, uint32_t, void*, size_t);
TimeType TimePtr;
GetTimeOfDayType GetTimeOfDayPtr;
ClockGetTimeType ClockGetTimePtr;
ClockGetResType ClockGetResPtr;
GetCPUType GetCPUPtr;
GetRandomType GetRandomPtr;
} // namespace VDSOHandlers
using HandlerPtr = void (*)(void*);
@ -99,6 +101,39 @@ namespace x64 {
int Result = FHU::Syscalls::getcpu(args->cpu, args->node);
args->rv = SyscallRet(Result);
}
static void getrandom(void* ArgsRV) {
struct vgetrandom_opaque_params {
uint32_t size_of_opaque_state;
uint32_t mmap_prot;
uint32_t mmap_flags;
uint32_t reserved[13];
};
static_assert(sizeof(vgetrandom_opaque_params) == sizeof(uint32_t[16]));
struct __attribute__((packed)) ArgsRV_t {
void* buffer;
size_t len;
uint32_t flags;
vgetrandom_opaque_params* opaque_state;
size_t opaque_len;
ssize_t rv;
}* args = reinterpret_cast<ArgsRV_t*>(ArgsRV);
if (args->buffer == nullptr && args->len == 0 && args->flags == 0 && args->opaque_len == ~0ULL) [[unlikely]] {
// Special case querying for flags
// Since this is the syscall implementation, we need to return valid but unused data.
// This will cause glibc to allocate a page of memory, but it ends up being unused.
args->opaque_state->size_of_opaque_state = 4096;
args->opaque_state->mmap_prot = PROT_NONE;
args->opaque_state->mmap_flags = MAP_NORESERVE | MAP_ANONYMOUS | MAP_PRIVATE;
args->rv = 0;
return;
}
int Result = ::syscall(SYS_getrandom, args->buffer, args->len, args->flags);
args->rv = SyscallRet(Result);
}
} // namespace glibc
namespace VDSO {
@ -151,6 +186,19 @@ namespace x64 {
args->rv = VDSOHandlers::GetCPUPtr(args->cpu, args->node);
}
static void getrandom(void* ArgsRV) {
struct __attribute__((packed)) ArgsRV_t {
void* buffer;
size_t len;
uint32_t flags;
void* opaque_state;
size_t opaque_len;
ssize_t rv;
}* args = reinterpret_cast<ArgsRV_t*>(ArgsRV);
args->rv = VDSOHandlers::GetRandomPtr(args->buffer, args->len, args->flags, args->opaque_state, args->opaque_len);
}
} // namespace VDSO
HandlerPtr Handler_time = FEX::VDSO::x64::glibc::time;
@ -158,6 +206,7 @@ namespace x64 {
HandlerPtr Handler_clock_gettime = FEX::VDSO::x64::glibc::clock_gettime;
HandlerPtr Handler_clock_getres = FEX::VDSO::x64::glibc::clock_getres;
HandlerPtr Handler_getcpu = FEX::VDSO::x64::glibc::getcpu;
HandlerPtr Handler_getrandom = FEX::VDSO::x64::glibc::getrandom;
} // namespace x64
namespace x32 {
namespace glibc {
@ -488,9 +537,20 @@ void LoadHostVDSO() {
x64::Handler_getcpu = x64::VDSO::getcpu;
x32::Handler_getcpu = x32::VDSO::getcpu;
}
SymbolPtr = VDSO.FindSymbol("__kernel_getrandom");
if (!SymbolPtr) {
SymbolPtr = VDSO.FindSymbol("__vdso_getrandom");
}
if (SymbolPtr) {
VDSOHandlers::GetRandomPtr = reinterpret_cast<VDSOHandlers::GetRandomType>(SymbolPtr);
x64::Handler_getrandom = x64::VDSO::getrandom;
// 32-bit doesn't have getrandom vdso
}
}
static std::array<FEXCore::IR::ThunkDefinition, 6> VDSODefinitions = {{
static std::array<FEXCore::IR::ThunkDefinition, 7> VDSODefinitions = {{
{
// sha256(libVDSO:time)
{0x37, 0x63, 0x46, 0xb0, 0x79, 0x06, 0x5f, 0x9d, 0x00, 0xb6, 0x8d, 0xfd, 0x9e, 0x4a, 0x62, 0xcd,
@ -529,6 +589,12 @@ static std::array<FEXCore::IR::ThunkDefinition, 6> VDSODefinitions = {{
0xbb, 0x50, 0x49, 0x55, 0x6b, 0x0c, 0x9f, 0x50, 0x37, 0xf5, 0x9d, 0xb0, 0x38, 0x58, 0x57, 0x12},
nullptr,
},
{
// sha256(libVDSO:getrandom)
{0xf8, 0x03, 0xe2, 0x70, 0xe3, 0xf1, 0xbb, 0xc1, 0x7d, 0xa7, 0x8b, 0xb3, 0x1f, 0x3e, 0xbd, 0xc6,
0x8a, 0x50, 0xd3, 0x4a, 0x1f, 0xb3, 0x4b, 0x7e, 0x32, 0xcb, 0x1e, 0x18, 0x3b, 0x7c, 0xeb, 0x4b},
nullptr,
},
}};
void LoadGuestVDSOSymbols(bool Is64Bit, char* VDSOBase) {
@ -702,6 +768,7 @@ VDSOMapping LoadVDSOThunks(bool Is64Bit, FEX::HLE::SyscallHandler* const Handler
VDSODefinitions[3].ThunkFunction = FEX::VDSO::x64::Handler_clock_gettime;
VDSODefinitions[4].ThunkFunction = FEX::VDSO::x64::Handler_clock_getres;
VDSODefinitions[5].ThunkFunction = FEX::VDSO::x64::Handler_getcpu;
VDSODefinitions[6].ThunkFunction = FEX::VDSO::x64::Handler_getrandom;
} else {
// Set the Thunk definition pointers for x86
VDSODefinitions[0].ThunkFunction = FEX::VDSO::x32::Handler_time;
@ -710,6 +777,7 @@ VDSOMapping LoadVDSOThunks(bool Is64Bit, FEX::HLE::SyscallHandler* const Handler
VDSODefinitions[3].ThunkFunction = FEX::VDSO::x32::Handler_clock_gettime64;
VDSODefinitions[4].ThunkFunction = FEX::VDSO::x32::Handler_clock_getres;
VDSODefinitions[5].ThunkFunction = FEX::VDSO::x32::Handler_getcpu;
// getrandom doesn't exist on 32-bit, so leave VDSODefinitions[6] unfilled
}
return Mapping;
@ -730,8 +798,8 @@ uint64_t GetVSyscallEntry(const void* VDSOBase) {
return 0;
}
const std::span<FEXCore::IR::ThunkDefinition> GetVDSOThunkDefinitions() {
return VDSODefinitions;
const std::span<FEXCore::IR::ThunkDefinition> GetVDSOThunkDefinitions(bool Is64Bit) {
return std::span(VDSODefinitions.begin(), VDSODefinitions.end() - (Is64Bit ? 0 : 1));
}
const VDSOSigReturn& GetVDSOSymbols() {

View File

@ -23,6 +23,6 @@ void UnloadVDSOMapping(const VDSOMapping& Mapping);
uint64_t GetVSyscallEntry(const void* VDSOBase);
const std::span<FEXCore::IR::ThunkDefinition> GetVDSOThunkDefinitions();
const std::span<FEXCore::IR::ThunkDefinition> GetVDSOThunkDefinitions(bool Is64Bit);
const VDSOSigReturn& GetVDSOSymbols();
} // namespace FEX::VDSO

View File

@ -58,6 +58,7 @@ __attribute__((naked)) void __kernel_rt_sigreturn() {
)" ::
: "memory");
}
#else
ssize_t __vdso_getrandom(void*, size_t, uint32_t, void*, size_t) __attribute__((alias("fexfn_pack_getrandom")));
#endif
}

View File

@ -47,6 +47,8 @@ VERSION {
clock_getres;
__vdso_getcpu;
getcpu;
__vdso_getrandom;
getrandom;
local: *;
};
}

View File

@ -2,6 +2,7 @@
#include <sched.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include "Types.h"
@ -24,4 +25,8 @@ struct fex_gen_config<getcpu> {};
extern int clock_gettime64(clockid_t __clock_id, struct timespec64* __tp) __THROW;
template<>
struct fex_gen_config<clock_gettime64> {};
#else
extern ssize_t getrandom(void* buffer, size_t len, uint32_t flags, void* opaque_state, size_t opaque_len);
template<>
struct fex_gen_config<getrandom> {};
#endif