MmFreePages() doesn't have the same NumberOfPages check that MmInternalAllocatePagesEx() has (SMM_FREE_PAGE)
Closed this issue · 0 comments
The supervisor calls MmFreePages() to free pages previously allocated with a call to SMM_ALOC_PAGE. In the SMM_ALOC_PAGE case, a call is made to MmAllocatePages(), which eventually lands inside of MmInternalAllocatePagesEx(), which makes sure the number of pages provided by user space can't be too large (no more than 48 bits essentially, as any more pages would require more memory than the 64-bit address space would logically allow for). This check makes a lot of sense.
Unfortunately, MmAllocatePages()'s counterpart, MmFreePages() has no such check. The number of pages provided by userland callers can be > 48 bits big. When converted to actual size (using the EFI_PAGES_TO_SIZE() macro), an integer overflow can lead the code to believe that fewer pages than required are being freed.
If the heap guard is enabled and the memory is guarded, in that case, ClearGuardedMemoryBits() loops over a bitmap based on the number of pages (without using the EFI_PAGES_TO_SIZE() macro). The worst-case scenario would be some kind of memory corruption.
Fix recommendation:
Adding a check like MmInternalAllocatePagesEx() has. And add an overflow check for user page free call in the syscall dispatcher.
Acknowledgement:
Thanks to @iljavs for reporting this issue.