Skip to content

Validate the shared memory manager pointer before adopting it (#84)#95

Open
TetzkatLipHoka wants to merge 1 commit into
pleriche:masterfrom
TetzkatLipHoka:harden-shared-memory-manager-discovery
Open

Validate the shared memory manager pointer before adopting it (#84)#95
TetzkatLipHoka wants to merge 1 commit into
pleriche:masterfrom
TetzkatLipHoka:harden-shared-memory-manager-discovery

Conversation

@TetzkatLipHoka

Copy link
Copy Markdown

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_AttemptToUseSharedMemoryManager copies LPMemoryManagerEx^, the record is now checked:

  • the whole TMemoryManagerEx 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. A genuine provider's record - a real TMemoryManagerEx in 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 existing OS_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

…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant