fix(psml): check the shared resources and add the context under one lock

A concurrent scePsmlMfsrReleaseSharedResources could pass its "still used
by a context" check between the handle lookup and the context insertion.
The technical debt entry now says how KytyPS5's layout differs from the
calls in PPSA08330 and PPSA03016.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ps54allandClaude Opus 5.5 authored and Adrià Franch committed 2026-10-16 20:41:44 +02:00
1 parent 7ab3d441c1
commit 46fdfec852
2 files changed
+9 -10

No files matched your search

+8 -9
View File
@@ -70,9 +70,13 @@ void RequireBlocks(const MfsrBlock* blocks, std::uint64_t blockCount, const char
}
}
void* CreateMfsrObject(MfsrObjectKind kind, void* sharedResources) {
auto* object = new MfsrObject{kind, sharedResources};
void* CreateMfsrObject(MfsrObjectKind kind, void* sharedResources, const char* function) {
std::lock_guard lock(g_mfsrMutex);
if (kind == MfsrObjectKind::Context) {
const auto found = g_mfsrObjects.find(sharedResources);
RequireMfsr(found != g_mfsrObjects.end() && found->second->kind == MfsrObjectKind::SharedResources, function, "shared resources handle was not created by this library");
}
auto* object = new MfsrObject{kind, sharedResources};
g_mfsrObjects.emplace(object, object);
return object;
}
@@ -134,7 +138,7 @@ std::int32_t APS5_VABI scePsmlMfsrCreateSharedResources(void** sharedResources,
RequireMfsr(sharedResources != nullptr && param != nullptr, __func__, "null handle or parameter");
RequireMfsr(param->type == 0, __func__, ("shared resources type " + std::to_string(param->type) + " is not supported").c_str());
RequireBlocks(param->blocks, param->blockCount, __func__);
*sharedResources = CreateMfsrObject(MfsrObjectKind::SharedResources, nullptr);
*sharedResources = CreateMfsrObject(MfsrObjectKind::SharedResources, nullptr, __func__);
return 0;
}
@@ -155,12 +159,7 @@ std::int32_t APS5_VABI scePsmlMfsrCreateContext800M3_2(void** context, const Mfs
if (!g_mfsrInitialized) return SCE_PSML_ERROR_NOT_INITIALIZED;
RequireMfsr(context != nullptr && param != nullptr, __func__, "null handle or parameter");
RequireBlocks(param->blocks, param->blockCount, __func__);
{
std::lock_guard lock(g_mfsrMutex);
const auto found = g_mfsrObjects.find(param->sharedResources);
RequireMfsr(found != g_mfsrObjects.end() && found->second->kind == MfsrObjectKind::SharedResources, __func__, "shared resources handle was not created by this library");
}
*context = CreateMfsrObject(MfsrObjectKind::Context, param->sharedResources);
*context = CreateMfsrObject(MfsrObjectKind::Context, param->sharedResources, __func__);
return 0;
}
+1 -1
View File
@@ -2,7 +2,7 @@
### Unknown function info
- [scePsmlMfsrGetSharedResourcesInitRequirement, scePsmlMfsrCreateSharedResources, scePsmlMfsrReleaseSharedResources, scePsmlMfsrGetContextBufferRequirement800M3_2, scePsmlMfsrCreateContext800M3_2, scePsmlMfsrReleaseContext](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - signatures from the calls in PPSA08330 (0x5724b6-0x5727e8, 0xc8697) and PPSA03016 (0x43dcf4d-0x43dd69a): a `{block bytes, alignment, block count}` requirement, a 32-byte shared-resources parameter with the type at 0 and the `{address, bytes}` block list at 8 and 16, a context parameter with the block list at 8 and 16 and the shared-resources handle at 0x38, and 8-byte handles written through the first argument and passed back by value. The other context parameter fields (a 16-bit size pair at 0x18, two descriptor pointers at 0x20 and 0x28) are not read. The requirement of four 2 MiB blocks, 2 MiB aligned, is what PPSA08330 v06.006 allocates regardless of the returned count; Sony's values are unknown ([KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/9e41d8320a2774b303fbad344c2347e8d0292e83/src/libs/libPsml.cpp) derives 52 blocks for type 0). Only type 0 is accepted. The error codes for null pointers, short block lists and foreign handles are unknown, so those calls throw
- [scePsmlMfsrGetSharedResourcesInitRequirement, scePsmlMfsrCreateSharedResources, scePsmlMfsrReleaseSharedResources, scePsmlMfsrGetContextBufferRequirement800M3_2, scePsmlMfsrCreateContext800M3_2, scePsmlMfsrReleaseContext](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - signatures from the calls in PPSA08330 (0x5724b6-0x5727e8, 0xc8697) and PPSA03016 (0x43dcf4d-0x43dd69a): a `{block bytes, alignment, block count}` requirement, a 32-byte shared-resources parameter with the type at 0 and the `{address, bytes}` block list at 8 and 16, a context parameter with the block list at 8 and 16 and the shared-resources handle at 0x38, and 8-byte handles written through the first argument and passed back by value. The other context parameter fields (a 16-bit size pair at 0x18, two descriptor pointers at 0x20 and 0x28) are not read. The requirement of four 2 MiB blocks, 2 MiB aligned, is what PPSA08330 v06.006 allocates regardless of the returned count; Sony's values are unknown ([KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/9e41d8320a2774b303fbad344c2347e8d0292e83/src/libs/libPsml.cpp) derives 52 blocks for type 0; its layout differs from these calls: it writes a 0x30-byte object through the first argument, where PPSA08330 passes one of two adjacent 8-byte handle globals, and reads the shared resources at context parameter offset 8, where both titles pass the block list). Only type 0 is accepted. The error codes for null pointers, short block lists and foreign handles are unknown, so those calls throw
- [scePsmlMfsr2CreateContext, scePsmlMfsr2CreateSharedResources, scePsmlMfsr2GetContextInitRequirement, scePsmlMfsr2GetDispatchPackets, scePsmlMfsr2GetDispatchPacketsSizeInDwords, scePsmlMfsr2GetSharedResourcesInitRequirement, scePsmlMfsr2Init, scePsmlMfsr2ReleaseContext, scePsmlMfsr2ReleaseSharedResources](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml_mfsr2) - unknown signatures, imported by PPSA23566; declared without parameters
- [scePsmlMfsrGetContextBufferRequirement1100, scePsmlMfsrCreateContext1100, scePsmlMfsrGetDispatchMfsrPacket1100](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml_debug) - argument layouts unknown; PPSA26344 imports but does not call the first two and at `0x87EFA` passes `(rdi, rsi=&stack, rdx)` as three pointers to `GetDispatchMfsrPacket1100`; before `scePsmlMfsrInit` they return 0x8A810001 (not initialized) and after it they throw. `scePsmlMfsrCreateContext1300` and `scePsmlMfsrGetDispatchMfsrPacket900`, `1000` and `1300` take the same shapes (context slot and parameter; context, command buffer and parameter) and behave the same way. PPSA08330 and PPSA03016 pass `GetDispatchMfsrPacket900`/`1000` the context handle, a `{cursor, size in dwords}` command buffer and the dispatch parameters, and advance their cursor by the size `scePsmlMfsrGetDispatchMfsrPacketSizeInDwords` returned. Whether the 1100 and 1300 versions take these arguments, and the console's error, are unverified
- [scePsmlMfsrGetDispatchMfsrPacket1000](../../../core/libs/prx/libScePsml_debug/Export.cpp) (libScePsml) - imported by PPSA25344. libScePsml and libScePsml_debug are built from the same source