Merge pull request #12556 from babyhuey/fix/sched-efault

fix(libkernel): return EFAULT from rtprio_thread and sched_rr_get_interval for a bad pointer
This commit is contained in:
Adrià authored and GitHub committed 2026-10-30 02:32:23 +01:00
commit 87d938c650
4 files changed
+30 -6

No files matched your search

@@ -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<std::int64_t>(lwpid) != static_cast<std::int64_t>(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<std::uint16_t>(schedPriority) : 0;
GuestRtPrio current{};
current.type = realTime ? (policy == GuestSchedFifo ? Fifo : Realtime) : Normal;
current.prio = realTime ? static_cast<std::uint16_t>(schedPriority) : 0;
if (!GuestCopyOut_nid_no_patch(priority, &current, 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");
}
+2 -3
View File
@@ -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<int>(Fail(GuestEsrch));
if (interval == nullptr) return static_cast<int>(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<int>(Fail(GuestEfault));
return 0;
}
+11
View File
@@ -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<GuestRtPrio*>(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<GuestRtPrio*>(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;
+10
View File
@@ -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<KernelTimespec*>(std::uintptr_t{0x10})) == -1 && *__error_nid_postfix() == 14);
*__error_nid_postfix() = 0;
Require(sched_rr_get_interval_nid_postfix(-1, reinterpret_cast<KernelTimespec*>(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<KernelTimespec*>(page)) == -1 && *__error_nid_postfix() == 14);
Require(static_cast<KernelTimespec*>(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);