Merge pull request #3700 from pushkarreddyy/feat/libkernel-sysctl-kern-arandom
feat(libkernel): support MIB 1.37 (kern.arandom) in sysctl
This commit is contained in:
commit
7300101fa2
|
|
@ -128,6 +128,21 @@ int APS5_VABI sysctl_nid_postfix(const int* name, std::uint32_t nameLength, void
|
|||
static constexpr char path[] = "/app0/eboot.bin";
|
||||
return CopyOut(path, sizeof(path), oldValue, oldLength);
|
||||
}
|
||||
if (nameLength == 2 && name[0] == 1 && name[1] == 37) {
|
||||
if (newValue != nullptr) {
|
||||
*__error_nid_postfix() = 1;
|
||||
return -1;
|
||||
}
|
||||
if (oldLength == nullptr) return 0;
|
||||
const std::size_t count = std::min(*oldLength, static_cast<std::size_t>(256));
|
||||
if (oldValue != nullptr) {
|
||||
static std::random_device device;
|
||||
auto* bytes = static_cast<std::uint8_t*>(oldValue);
|
||||
for (std::size_t i = 0; i < count; ++i) bytes[i] = static_cast<std::uint8_t>(device());
|
||||
}
|
||||
*oldLength = count;
|
||||
return 0;
|
||||
}
|
||||
std::string mib;
|
||||
for (std::uint32_t i = 0; i < nameLength; ++i) mib += (i == 0 ? "" : ".") + std::to_string(name[i]);
|
||||
throw std::runtime_error(std::string(__func__) + ": unsupported MIB " + mib);
|
||||
|
|
@ -146,6 +161,10 @@ int APS5_VABI sysctlbyname_nid_postfix(const char* name, void* oldValue, std::si
|
|||
*__error_nid_postfix() = 22;
|
||||
return -1;
|
||||
}
|
||||
if (std::strcmp(name, "kern.arandom") == 0) {
|
||||
static constexpr int mib[] = {1, 37};
|
||||
return sysctl_nid_postfix(mib, 2, oldValue, oldLength, newValue, newLength);
|
||||
}
|
||||
if (std::strcmp(name, "kern.rng_pseudo") == 0) {
|
||||
if (newValue != nullptr) {
|
||||
*__error_nid_postfix() = 1;
|
||||
|
|
|
|||
|
|
@ -194,6 +194,41 @@ static void CheckSdkVersionSysctl() {
|
|||
length = sizeof(version);
|
||||
Require(sysctlbyname_nid_postfix("kern.sdk_version", &version, &length, &version, sizeof(version)) == -1 && *__error_nid_postfix() == 1);
|
||||
}
|
||||
static void CheckArandomSysctl() {
|
||||
const int mib[] = {1, 37};
|
||||
*__error_nid_postfix() = 13;
|
||||
std::size_t length = 0;
|
||||
Require(sysctl_nid_postfix(mib, 2, nullptr, &length, nullptr, 0) == 0 && length == 0);
|
||||
length = 64;
|
||||
Require(sysctl_nid_postfix(mib, 2, nullptr, &length, nullptr, 0) == 0 && length == 64);
|
||||
length = 300;
|
||||
Require(sysctl_nid_postfix(mib, 2, nullptr, &length, nullptr, 0) == 0 && length == 256);
|
||||
Require(sysctl_nid_postfix(mib, 2, nullptr, nullptr, nullptr, 0) == 0);
|
||||
Require(*__error_nid_postfix() == 13);
|
||||
unsigned char first[64] = {};
|
||||
unsigned char second[64] = {};
|
||||
length = sizeof(first);
|
||||
Require(sysctl_nid_postfix(mib, 2, first, &length, nullptr, 0) == 0 && length == sizeof(first));
|
||||
length = sizeof(second);
|
||||
Require(sysctl_nid_postfix(mib, 2, second, &length, nullptr, 0) == 0 && length == sizeof(second));
|
||||
Require(std::memcmp(first, second, sizeof(first)) != 0);
|
||||
Require(*__error_nid_postfix() == 13);
|
||||
unsigned char named[64] = {};
|
||||
length = sizeof(named);
|
||||
Require(sysctlbyname_nid_postfix("kern.arandom", named, &length, nullptr, 0) == 0 && length == sizeof(named));
|
||||
Require(*__error_nid_postfix() == 13);
|
||||
length = sizeof(first);
|
||||
Require(sysctl_nid_postfix(mib, 2, first, &length, first, sizeof(first)) == -1 && *__error_nid_postfix() == 1);
|
||||
*__error_nid_postfix() = 13;
|
||||
unsigned char big[300] = {};
|
||||
length = sizeof(big);
|
||||
Require(sysctl_nid_postfix(mib, 2, big, &length, nullptr, 0) == 0 && length == 256);
|
||||
unsigned char small[16] = {};
|
||||
length = sizeof(small);
|
||||
Require(sysctl_nid_postfix(mib, 2, small, &length, nullptr, 0) == 0 && length == sizeof(small));
|
||||
Require(sysctl_nid_postfix(mib, 2, first, nullptr, nullptr, 0) == 0);
|
||||
Require(*__error_nid_postfix() == 13);
|
||||
}
|
||||
int main() {
|
||||
CheckProcessorCountSysctl();
|
||||
CheckPhysicalMemorySysctl();
|
||||
|
|
@ -202,6 +237,7 @@ int main() {
|
|||
CheckSystemSwVersion();
|
||||
CheckPseudoRandomSysctl();
|
||||
CheckSdkVersionSysctl();
|
||||
CheckArandomSysctl();
|
||||
*__error_nid_postfix() = 13;
|
||||
Require(sysconf_nid_postfix(47) == 0x4000);
|
||||
Require(getpagesize_nid_postfix() == sysconf_nid_postfix(47));
|
||||
|
|
|
|||
|
|
@ -710,3 +710,4 @@ Throughout the project, every function at every stage either **does exactly what
|
|||
- [sceAgcCreatePrimState](../../core/libs/prx/libSceAgc/Shader/src/PrimState.cpp) (libSceAgc) - the `ge_user_vgpr_en` special is passed to the user configuration registers at whatever offset the shader header stores, as the SPRX does according to [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/3c7e8072f0d7684e930454794fd5c02056946d73/src/game_compat.c#L1181-L1252), which copies all four specials verbatim (KytyPS5 stops on any other offset). PPSA99039, PPSA99505, PPSA99515 and PPSA99997 build their headers by hand with it at 0x25c (`GE_USER_VGPR1`) instead of 0x262 (`GE_USER_VGPR_EN`), value 0, and run on the console; it is not moved to 0x262, and the driver reads neither register. `ge_cntl`, `vgt_shader_stages_en` and a used `vgt_gs_out_prim_type` must still be at their own offsets, since the driver reads those registers there, so a header that stores one elsewhere throws naming the offset, although by OpenAGC the SPRX would copy it as well
|
||||
- [pthread_spin_init, pthread_spin_destroy, pthread_spin_lock, pthread_spin_trylock, pthread_spin_unlock](../../core/libs/prx/libkernel/Pthread/Posix/Spinlock.cpp) (libkernel) follow FreeBSD 11.4 libthr [`thr_pspinlock.c`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libthr/thread/thr_pspinlock.c) and the owner checks of its [`thr_umtx.h`](https://github.com/freebsd/freebsd-src/blob/8c639945a44588f6cfdddfb057bb5aad88735da0/lib/libthr/thread/thr_umtx.h#L80-L175), unverified on the console: `EINVAL` for a null or destroyed lock and a `pshared` other than 0 or 1, `EBUSY` from `trylock` while any thread holds it, `EPERM` from `unlock` by a thread that does not hold it. `PTHREAD_PROCESS_SHARED` allocates a private lock, as guest code runs in one process. libthr spins forever when the holder locks again; here that call throws
|
||||
- [pthread_cond_reltimedwait_np](../../core/libs/prx/libkernel/Pthread/Posix/Cond.cpp) (libkernel) takes `(cond, mutex, usec)`, a relative timeout in microseconds, and is `scePthreadCondTimedwait` with POSIX error numbers. FreeBSD 11.4 has no such function; the signature comes only from shadPS4, which registers one function for this NID and for `scePthreadCondTimedwait` ([`condvar.cpp`](https://github.com/shadps4-emu/shadPS4/blob/3a9f57265d28975658f1ca941daa5c879c7a74bd/src/core/libraries/kernel/threads/condvar.cpp#L229-L234)). shadPS4 reads a 64-bit count; here it is the 32-bit `SceKernelUseconds` of the SCE twin, as for `sem_reltimedwait_np`. Unverified on the console
|
||||
- [sysctl kern.arandom](../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) serves FreeBSD 11's MIB {1, 37} (CTL_KERN, KERN_ARANDOM) and the "kern.arandom" sysctlbyname lookup through std::random_device, returning min(*oldLength, 256) random bytes. Following FreeBSD's sysctl_kern_arnd, a null buffer reports min(*oldLength, 256) without writing, a null length returns 0 without writing, and requests with a new value return EPERM (1) as the node is read-only. Cryptographic quality depends on the host's random device implementation.
|
||||
|
|
|
|||
Loading…
Reference in New Issue