Give the memory partitions the caller's privilege, not the syscall's

PPSSPP decided whether a caller was privileged with hleIsKernelMode(), which reports whether the
syscall being executed is itself a kernel-only export. That's a different question from the one
the hardware answers: on a PSP the privilege belongs to the calling module, and a kernel module
reaches sceKernelCreateTlspl through the ordinary ThreadManForUser NID like anything else. So a
kernel module asking for partition 1, 3 or 4 got ILLEGAL_PERM where a real PSP hands it over,
which the new threads/tls/kernel/partition test shows directly.

BlockAllocatorFromID now also accepts a caller whose thread belongs to a kernel module, via a new
__KernelCurThreadIsKernelMode(). It checks the thread's own attribute first and then the owning
module, because a kernel module's main thread isn't necessarily flagged kernel - the attribute
comes from PSP_MAIN_THREAD_ATTR, which needn't set it. That mirrors how sceKernelCreateThread
already works out allowKernel.

This only ever widens access, and only for threads belonging to kernel modules, so games are
unaffected - they run in user modules and see exactly what they saw before.
This commit is contained in:
Henrik Rydgård committed 2026-09-08 15:18:02 -06:00
1 parent a676eecba7
commit 41144e3b35
6 files changed
+35 -6

No files matched your search

+11
View File
@@ -2290,6 +2290,17 @@ SceUID __KernelGetCurThreadModuleId() {
return 0;
}
bool __KernelCurThreadIsKernelMode() {
PSPThread *thread = __GetCurrentThread();
if (thread && (thread->nt.attr & PSP_THREAD_ATTR_KERNEL) != 0) {
return true;
}
// A kernel module's own main thread isn't necessarily flagged kernel - the attribute comes
// from PSP_MAIN_THREAD_ATTR in the module info, which needn't set it - so fall back to what
// module the thread belongs to, the same way sceKernelCreateThread decides allowKernel.
return KernelModuleIsKernelMode(__KernelGetCurThreadModuleId());
}
u32 __KernelGetCurThreadStack() {
PSPThread *t = __GetCurrentThread();
if (t)