diff --git a/core/libs/prx/libkernel/Pthread/Posix/Thread.cpp b/core/libs/prx/libkernel/Pthread/Posix/Thread.cpp index 89e978d708..4fff7c3a22 100644 --- a/core/libs/prx/libkernel/Pthread/Posix/Thread.cpp +++ b/core/libs/prx/libkernel/Pthread/Posix/Thread.cpp @@ -126,15 +126,19 @@ int APS5_VABI rtprio_thread_nid_postfix(int function, int lwpid, GuestRtPrio* pr int schedPriority = self->priority.load(std::memory_order_relaxed); const bool other = lwpid != 0 && static_cast(lwpid) != static_cast(self->tid); if (other && !GetLiveGuestThreadSched_nid_no_patch(lwpid, policy, schedPriority)) return fail(GuestEsrch); + GuestRtPrio requested{}; + if (function == Set && !GuestCopyIn_nid_no_patch(&requested, priority, sizeof(requested))) return fail(GuestEfault); const bool realTime = policy == GuestSchedFifo || policy == GuestSchedRr; if (function == Lookup) { - priority->type = realTime ? (policy == GuestSchedFifo ? Fifo : Realtime) : Normal; - priority->prio = realTime ? static_cast(schedPriority) : 0; + GuestRtPrio current{}; + current.type = realTime ? (policy == GuestSchedFifo ? Fifo : Realtime) : Normal; + current.prio = realTime ? static_cast(schedPriority) : 0; + if (!GuestCopyOut_nid_no_patch(priority, ¤t, sizeof(current))) return fail(GuestEfault); return 0; } if (other) NotImplemented_nid_no_patch("rtprio_thread: a thread other than the calling one"); if (realTime) NotImplemented_nid_no_patch("rtprio_thread: a guest thread's real-time class"); - if (priority->type == Normal && priority->prio == 0) return 0; + if (requested.type == Normal && requested.prio == 0) return 0; NotImplemented_nid_no_patch("rtprio_thread: a real-time priority change"); } diff --git a/core/libs/prx/libkernel_sys/Export.cpp b/core/libs/prx/libkernel_sys/Export.cpp index 1195d93f25..de60e1a45c 100644 --- a/core/libs/prx/libkernel_sys/Export.cpp +++ b/core/libs/prx/libkernel_sys/Export.cpp @@ -986,9 +986,8 @@ int APS5_VABI sched_rr_get_interval_nid_postfix(int pid, KernelTimespec* interva constexpr int GuestEsrch = 3; const int self = getpid_nid_postfix(); if (pid != 0 && pid != self) return static_cast(Fail(GuestEsrch)); - if (interval == nullptr) return static_cast(Fail(GuestEfault)); - interval->tv_sec = 0; - interval->tv_nsec = 94000000; + const KernelTimespec quantum{0, 94000000}; + if (interval == nullptr || !GuestCopyOut_nid_no_patch(interval, &quantum, sizeof(quantum))) return static_cast(Fail(GuestEfault)); return 0; } diff --git a/core/libs/tests/GuestRtprioThread.cpp b/core/libs/tests/GuestRtprioThread.cpp index 0d44857120..a9ec33d1f7 100644 --- a/core/libs/tests/GuestRtprioThread.cpp +++ b/core/libs/tests/GuestRtprioThread.cpp @@ -92,6 +92,17 @@ int main() { CheckThread(GUEST_SCHED_FIFO, 256, RTP_PRIO_FIFO); Require(LookupError(2, 0, &self) == GUEST_ESRCH); Require(LookupError(RTP_LOOKUP, 0, nullptr) == GUEST_EFAULT); + auto* unmapped = reinterpret_cast(std::uintptr_t{0x10}); + Require(LookupError(RTP_LOOKUP, 0, unmapped) == GUEST_EFAULT); + Require(LookupError(RTP_SET, 0, unmapped) == GUEST_EFAULT); + Require(LookupError(RTP_SET, 999999, unmapped) == GUEST_ESRCH); + void* page = nullptr; + Require(sceKernelMapFlexibleMemory(&page, 0x4000, 3, 0) == 0 && page != nullptr); + auto* readOnly = static_cast(page); + *readOnly = {7, 7}; + Require(sceKernelMprotect(page, 0x4000, 1) == 0); + Require(LookupError(RTP_LOOKUP, 0, readOnly) == GUEST_EFAULT); + Require(readOnly->type == 7 && readOnly->prio == 7); Require(LookupError(RTP_LOOKUP, 1, &self) == GUEST_ESRCH); Require(LookupError(RTP_LOOKUP, 999999, &self) == GUEST_ESRCH); bool threw = false; diff --git a/core/libs/tests/GuestSchedPriority.cpp b/core/libs/tests/GuestSchedPriority.cpp index 27f7e23a90..8aaec24a56 100644 --- a/core/libs/tests/GuestSchedPriority.cpp +++ b/core/libs/tests/GuestSchedPriority.cpp @@ -54,6 +54,16 @@ int main() { Require(sched_rr_get_interval_nid_postfix(self + 1, &interval) == -1 && *__error_nid_postfix() == 3); *__error_nid_postfix() = 0; Require(sched_rr_get_interval_nid_postfix(0, nullptr) == -1 && *__error_nid_postfix() == 14); + *__error_nid_postfix() = 0; + Require(sched_rr_get_interval_nid_postfix(0, reinterpret_cast(std::uintptr_t{0x10})) == -1 && *__error_nid_postfix() == 14); + *__error_nid_postfix() = 0; + Require(sched_rr_get_interval_nid_postfix(-1, reinterpret_cast(std::uintptr_t{0x10})) == -1 && *__error_nid_postfix() == 3); + void* page = nullptr; + Require(sceKernelMapFlexibleMemory(&page, 0x4000, 3, 0) == 0 && page != nullptr); + Require(sceKernelMprotect(page, 0x4000, 1) == 0); + *__error_nid_postfix() = 0; + Require(sched_rr_get_interval_nid_postfix(0, static_cast(page)) == -1 && *__error_nid_postfix() == 14); + Require(static_cast(page)->tv_nsec == 0); for (int policy : {1, 3}) { Require(sched_get_priority_max_nid_postfix(policy) == 767); Require(sched_get_priority_min_nid_postfix(policy) == 256);