common: improve host memory mapping validation

- Add maximum memory size limit of 512GB (Overkill)
- Implement additional safety checks for memory mapping:
  * Validate non-zero addresses
  * Verify address alignment
  * Add length validation against maximum size
- Remove redundant assertion for host_offset alignment
- Remove potentially problematic mapping verification
- Improve error logging for invalid mapping attempts

These changes enhance memory safety by adding proper bounds
checking and validation before performing memory mappings,
while removing a potentially problematic post-mapping
verification step.
This commit is contained in:
Zephyron 2025-02-08 19:32:06 +10:00
parent c31768ec15
commit 7ecb890a16
No known key found for this signature in database

View file

@ -41,6 +41,7 @@ namespace Common {
constexpr size_t PageAlignment = 0x1000; constexpr size_t PageAlignment = 0x1000;
constexpr size_t HugePageSize = 0x200000; constexpr size_t HugePageSize = 0x200000;
constexpr size_t max_memory_size = 0x8000000000; // 512 GB max memory size
#ifdef _WIN32 #ifdef _WIN32
@ -112,7 +113,8 @@ public:
throw std::bad_alloc{}; throw std::bad_alloc{};
} }
// Allocate a virtual memory for the backing file map as placeholder // Allocate a virtual memory for the backing file map as placeholder
backing_base = static_cast<u8*>(pfn_VirtualAlloc2(process, nullptr, backing_size, backing_base =
static_cast<u8*>(pfn_VirtualAlloc2(process, nullptr, backing_size,
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
PAGE_NOACCESS, nullptr, 0)); PAGE_NOACCESS, nullptr, 0));
if (!backing_base) { if (!backing_base) {
@ -743,23 +745,33 @@ HostMemory& HostMemory::operator=(HostMemory&&) noexcept = default;
void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length, void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length,
MemoryPermission perms, bool separate_heap) { MemoryPermission perms, bool separate_heap) {
// Add additional checks before mapping
if (virtual_offset == 0 || host_offset == 0) {
LOG_ERROR(Common_Memory, "Invalid memory mapping addresses");
return;
}
// Ensure addresses are properly aligned
if ((virtual_offset & 0xFFF) != 0 || (host_offset & 0xFFF) != 0) {
LOG_ERROR(Common_Memory, "Unaligned memory mapping addresses");
return;
}
// Add size validation
if (length == 0 || length > max_memory_size) {
LOG_ERROR(Common_Memory, "Invalid mapping length: {}", length);
return;
}
ASSERT(virtual_offset % PageAlignment == 0); ASSERT(virtual_offset % PageAlignment == 0);
ASSERT(host_offset % PageAlignment == 0);
ASSERT(length % PageAlignment == 0); ASSERT(length % PageAlignment == 0);
ASSERT(virtual_offset + length <= virtual_size); ASSERT(virtual_offset + length <= virtual_size);
ASSERT(host_offset + length <= backing_size);
if (length == 0 || !virtual_base || !impl) { if (length == 0 || !virtual_base || !impl) {
return; return;
} }
impl->Map(virtual_offset + virtual_base_offset, host_offset, length, perms); impl->Map(virtual_offset + virtual_base_offset, host_offset, length, perms);
// Verify mapping was successful
if (!impl->IsValidMapping(virtual_offset + virtual_base_offset, length)) {
LOG_CRITICAL(Common_Memory, "Failed to verify memory mapping: virtual_offset={:x}, host_offset={:x}, length={:x}",
virtual_offset, host_offset, length);
}
} }
void HostMemory::Unmap(size_t virtual_offset, size_t length, bool separate_heap) { void HostMemory::Unmap(size_t virtual_offset, size_t length, bool separate_heap) {