Validate the shared memory manager pointer before adopting it (#84)#95
Open
TetzkatLipHoka wants to merge 1 commit into
Open
Conversation
…he#84) The shared memory manager is discovered through a named file mapping whose name contains only the (public) process ID in the session-scoped Local\ namespace, so a hostile process in the same session can pre-create the mapping and publish an arbitrary pointer. FastMM_AttemptToUseSharedMemoryManager then copies that pointer as a TMemoryManagerEx record (InstalledMemoryManager := LPMemoryManagerEx^), faulting on a planted/garbage pointer. Before the record is adopted it is now validated: the whole record must lie in committed, readable memory, and its three mandatory entry points (GetMem/FreeMem/ReallocMem) must point into committed, executable memory. An invalid pointer is treated as "no shared manager found" instead of being dereferenced, turning the attacker-triggered access violation into a graceful no-op. This is deliberately validation only - it does not add any structure, version or provenance field to the shared record, so it does not change the wire format and remains compatible with the memory managers of other FastMM versions and the built-in memory manager: a genuine provider's record (readable memory, executable entry points) passes unchanged. Verified with a same-process reproducer that plants the mapping for its own PID (indistinguishable from a hostile process's mapping from FastMM's point of view): before the change the target faults (runtime error 216); after it, a non-readable pointer and a readable-but-non-executable buffer are both rejected without a crash, while a valid record with real executable entry points is still adopted. Delphi 13.1, Win32 and Win64.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Re #84. I understand the reluctance to change how the shared manager is discovered - the mapping name has to stay compatible with older FastMM versions and the built-in memory manager, so version/provenance handshakes are out. This PR does not touch the discovery mechanism or the shared record format at all; it only adds a defensive validation of the pointer before it is dereferenced, which keeps the reported crash from happening while staying fully backward compatible.
Before
FastMM_AttemptToUseSharedMemoryManagercopiesLPMemoryManagerEx^, the record is now checked:TMemoryManagerExmust lie in committed, readable memory, andAn invalid pointer is treated as "no shared manager found" instead of being dereferenced. A genuine provider's record - a real
TMemoryManagerExin a module's data segment with real code entry points - passes unchanged, so sharing with other FastMM versions and the built-in MM is unaffected. Both checks reuse the existingOS_GetVirtualMemoryRegionInfo.This does not claim to establish provenance (a same-session process could still publish a valid manager); it only removes the attacker-triggered access violation, which was the demonstrated impact.
Verified with a same-process reproducer that plants the mapping for its own PID (indistinguishable from a hostile process's mapping from FastMM's point of view): before the change the target faults (runtime error 216); after it, a non-readable pointer and a readable-but-non-executable buffer are both rejected without a crash, while a valid record with real executable entry points is still adopted. Delphi 7 and 13.1, Win32 and Win64. Entirely up to you whether the availability hardening is worth it given the constraints - happy to adjust or drop it.
🤖 Generated with Claude Code