Validate requested dmem range in MapMemory

Handles a rare edge case that only comes up when modding Driveclub
This commit is contained in:
Stephen Miller 2025-06-21 13:39:13 -05:00
parent e389d03601
commit 607bd59a9c
2 changed files with 29 additions and 3 deletions

View File

@ -320,6 +320,28 @@ s32 MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, u64 size, Memo
return ORBIS_KERNEL_ERROR_ENOMEM; return ORBIS_KERNEL_ERROR_ENOMEM;
} }
// Validate the requested physical address range
if (phys_addr != -1) {
auto validated_size = 0;
do {
auto dmem_area = FindDmemArea(phys_addr + validated_size)->second;
// If any requested dmem area is not allocated, return an error.
if (dmem_area.is_free) {
LOG_ERROR(Kernel_Vmm, "Unable to map {:#x} bytes at physical address {:#x}", size,
phys_addr);
return ORBIS_KERNEL_ERROR_ENOMEM;
}
// Track how much we've validated.
validated_size += dmem_area.size - (phys_addr + validated_size - dmem_area.base);
} while (validated_size < size && phys_addr + validated_size < GetTotalDirectSize());
// If the requested range goes outside the dmem map, return an error.
if (validated_size < size) {
LOG_ERROR(Kernel_Vmm, "Unable to map {:#x} bytes at physical address {:#x}", size,
phys_addr);
return ORBIS_KERNEL_ERROR_ENOMEM;
}
}
// Limit the minumum address to SystemManagedVirtualBase to prevent hardware-specific issues. // Limit the minumum address to SystemManagedVirtualBase to prevent hardware-specific issues.
VAddr mapped_addr = (virtual_addr == 0) ? impl.SystemManagedVirtualBase() : virtual_addr; VAddr mapped_addr = (virtual_addr == 0) ? impl.SystemManagedVirtualBase() : virtual_addr;

View File

@ -63,8 +63,8 @@ enum class VMAType : u32 {
struct DirectMemoryArea { struct DirectMemoryArea {
PAddr base = 0; PAddr base = 0;
size_t size = 0; u64 size = 0;
int memory_type = 0; s32 memory_type = 0;
bool is_pooled = false; bool is_pooled = false;
bool is_free = true; bool is_free = true;
@ -72,6 +72,10 @@ struct DirectMemoryArea {
return base + size; return base + size;
} }
bool Contains(PAddr addr, u64 size) const {
return addr >= base && (addr + size) <= (base + this->size);
}
bool CanMergeWith(const DirectMemoryArea& next) const { bool CanMergeWith(const DirectMemoryArea& next) const {
if (base + size != next.base) { if (base + size != next.base) {
return false; return false;
@ -88,7 +92,7 @@ struct DirectMemoryArea {
struct VirtualMemoryArea { struct VirtualMemoryArea {
VAddr base = 0; VAddr base = 0;
size_t size = 0; u64 size = 0;
PAddr phys_base = 0; PAddr phys_base = 0;
VMAType type = VMAType::Free; VMAType type = VMAType::Free;
MemoryProt prot = MemoryProt::NoAccess; MemoryProt prot = MemoryProt::NoAccess;