Repository navigation
fix(libkernel): reprotect bundled guest module images on Windows - #1803
Conversation
MarcZX10
left a comment
There was a problem hiding this comment.
I found a module-lifetime issue in the new registration. registerImage adds committed .guest.prx pages to the global allocation registry as non-releasable and records the base in registeredImages, but guest modules can later be unloaded: sceKernelStopUnloadModule calls dlclose_nid_postfix, whose Windows Module destructor calls FreeLibrary. Nothing removes those registry ranges or the base from registeredImages on unload. This leaves dead image ranges registered, can make later mappings at the released address fail, and can expose stale addresses to GPU builds. Please add unload cleanup coordinated with outstanding allocation leases and cover mprotect → unload → reload/address reuse in a Windows test before approval.
|
Thanks, you're right: nothing undid the registration when a module was unloaded. Fixed in the new commit:
The test ( With the unregister call removed, the test fails at the "dlclose blocks while leased" check. Full build + ctest: 477/477 pass (Windows, MinGW, RTX 3070). |
|
|
|
@oneandonlydean done in 0040990:
Full build + ctest 477/477 on Windows (GCC 15.2 UCRT, RTX 3070); |
|
Conflicts with main in |
On Windows, sceKernelMprotect accepted only the executable's image and threw "Memory protection of a foreign image is not supported" for every other image. Bundled title modules are relinked into DLLs named <module>.guest.prx, so a title that reprotects its own module pages failed. Dying Light 2's bundled libNRD does this at start-up (boykopovar#1794). DoMprotect now also accepts images whose file name ends in .guest.prx, and registers their committed pages like the executable's. Other images are still refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A .guest.prx image registered by sceKernelMprotect stayed in the guest allocation registry after dlclose freed it, so its dead ranges blocked later mappings at that address and could reach GPU builds. The Windows module destructor now unregisters the image before FreeLibrary. Unregistering waits for outstanding leases on the image like unmap and protect do; if the wait fails the module stays loaded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…te failures Move the image unregistration out of the Module destructor into dlclose_nid_postfix. It runs while the handle is still registered, so a failure (the image stays leased by GPU work) propagates to the caller and leaves the module loaded and usable. Images shared by another open handle stay registered until the last handle closes. guest_memory now checks that dlclose under a held lease throws and keeps the module, its symbols and its protection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0040990 to
b1a14c6
Compare
adriadam10
left a comment
There was a problem hiding this comment.
Rebased onto current main as requested (single conflict in core/libs/tests/GuestMemory.cpp, main(): kept the _putenv_s under _WIN32 and the two new checks from main). Built and ran guest_memory and the libc/libkernel tests on Linux: green. The Windows case needs the Windows job; merging once CI is green.
|
Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.
|
What
Fixes item 4 of #1794. On Windows,
sceKernelMprotectaccepted only the executable's image and threwMemory protection of a foreign image is not supportedfor any other image. Bundled title modules are relinked into DLLs named<module>.guest.prx, so a title that reprotects pages of its own bundled module could not start. Dying Light 2's bundledlibNRDdoes this at start-up (prot=0x12over 0x11278 bytes, then0x11over 0x178540 bytes).DoMprotectnow also accepts images whose file name ends in.guest.prx. It registers their committed pages inGuestAllocationsthe same way as the executable's:RegisterMainImage's Windows walk becomes a per-image registration, and the executable is one caller. Any other image (system DLLs, AnyPS5's own.prxlibraries) is still refused.Tested
Windows 11, MinGW GCC 15.2.0, RTX 3070:
guest_memoryhas a new Windows case. It loads a small DLL namedguest_memory_module.guest.prxand reprotects a data page read-only, then writable (writes and checks a byte), then read-only again, checking the host protection each time. It also checks that a page ofkernel32.dllis still refused. Without the fix it fails withMemory protection of a foreign image is not supported; with it, it passes.ctest: 477/477 pass.python tools/check_conventions.py --base origin/mainpasses.libNRDreprotections now succeed, and the title continues to its ownNet_StartUp failedassertion (item 5 of Dying Light 2 (PPSA02262) on Windows: what stops it between conversion and its own startup #1794, unrelated to this change). The other items of Dying Light 2 (PPSA02262) on Windows: what stops it between conversion and its own startup #1794 were worked around locally for this run and are not part of this PR.Linux is unchanged. I did not build or run it.
Checklist
main; no other open PR implements the same functionsNotImplemented_nid_no_patch); silent stubs are listed in TechnicalDebt.mdfiles or images added to the repository (attach them to this PR)🤖 Generated with Claude Code