Files
AnyPS5/core/libs/tests/GuestOutputPointerFault.cpp
T
xXPBSXxandClaude Sonnet 5.5 c8430e739c fix(libkernel): fail gettimeofday, getitimer, setitimer and the sceKernel time getters with EFAULT on an unusable pointer
These wrote their result through the caller's pointer in place, or read
the itimerval of setitimer without a check, so a pointer into unmapped
memory crashed the host. Build the result locally and copy it out with
the checked write (and read the setitimer value with a checked read),
failing with EFAULT as FreeBSD 11.4 does: copyout in sys_gettimeofday
(sys/kern/kern_time.c:646 and 651) and sys_getitimer (kern_time.c:745),
copyin (kern_time.c:803) and copyout (kern_time.c:808) in sys_setitimer.

getrlimit and getrusage are left to #8986 and #8988, which cover the same
family for those two calls.

Builds on fix/output-structs-efault, which adds GuestCopyOut_nid_no_patch.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-25 12:22:40 +01:00

58 lines
2.3 KiB
C++

#include "prx/libc/include/Api.hpp"
#include "prx/libkernel/Time/include/Time.hpp"
#include "prx/libkernel/include/Api.hpp"
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <initializer_list>
static void Check(bool value, int line) {
if (!value) {
std::fprintf(stderr, "output pointer check failed at line %d\n", line);
std::abort();
}
}
#define Require(value) Check((value), __LINE__)
static constexpr int GuestEfault = 14;
static constexpr int KernelEfault = static_cast<int>(0x8002000Eu);
static bool Efault(int result) {
return result == -1 && *__error_nid_postfix() == GuestEfault;
}
int main() {
alignas(8) unsigned char valid[512]{};
alignas(8) unsigned char zeroTimer[32]{};
auto* timeValid = reinterpret_cast<KernelTimeval*>(valid);
auto* zoneValid = reinterpret_cast<KernelTimezone*>(valid + 32);
auto* timerValid = reinterpret_cast<GuestItimerval*>(valid);
auto* zeroTimerValue = reinterpret_cast<const GuestItimerval*>(zeroTimer);
for (const std::uintptr_t address : {std::uintptr_t{1}, ~std::uintptr_t{0xfff}}) {
void* bad = reinterpret_cast<void*>(address);
auto* badTime = reinterpret_cast<KernelTimeval*>(address);
auto* badZone = reinterpret_cast<KernelTimezone*>(address);
auto* badTimer = reinterpret_cast<GuestItimerval*>(address);
*__error_nid_postfix() = 0;
*__error_nid_postfix() = 0;
*__error_nid_postfix() = 0;
Require(Efault(gettimeofday_nid_postfix(badTime, nullptr)));
*__error_nid_postfix() = 0;
Require(Efault(gettimeofday_nid_postfix(timeValid, badZone)));
*__error_nid_postfix() = 0;
Require(Efault(getitimer_nid_postfix(0, badTimer)));
*__error_nid_postfix() = 0;
Require(Efault(setitimer_nid_postfix(0, zeroTimerValue, badTimer)));
*__error_nid_postfix() = 0;
Require(Efault(setitimer_nid_postfix(0, badTimer, timerValid)));
Require(sceKernelGettimeofday(badTime) == KernelEfault);
Require(sceKernelGettimezone(badZone) == KernelEfault);
}
Require(gettimeofday_nid_postfix(timeValid, zoneValid) == 0);
Require(getitimer_nid_postfix(0, timerValid) == 0);
Require(setitimer_nid_postfix(0, zeroTimerValue, timerValid) == 0);
Require(sceKernelGettimeofday(timeValid) == 0);
Require(sceKernelGettimezone(zoneValid) == 0);
}