From 33830aa65ac58a03a91de9ac4fc8d91fe28f6d4e Mon Sep 17 00:00:00 2001 From: Lioncash Date: Wed, 17 Oct 2018 22:39:21 -0400 Subject: svc: Add missing sanitizing checks for MapSharedMemory/UnmapSharedMemory Now that the changes clarifying the address spaces has been merged, we can wrap the checks that the kernel performs when mapping shared memory (and other forms of memory) into its own helper function and then use those within MapSharedMemory and UnmapSharedMemory to complete the sanitizing checks that are supposed to be done. --- src/core/hle/kernel/svc.cpp | 30 +++++++++++++++++++++++++++--- src/core/hle/kernel/vm_manager.cpp | 20 ++++++++++++++++++++ src/core/hle/kernel/vm_manager.h | 3 +++ 3 files changed, 50 insertions(+), 3 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index d08b84bde..d3971a25e 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -578,6 +578,10 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s return ERR_INVALID_SIZE; } + if (!IsValidAddressRange(addr, size)) { + return ERR_INVALID_ADDRESS_STATE; + } + const auto permissions_type = static_cast(permissions); if (permissions_type != MemoryPermission::Read && permissions_type != MemoryPermission::ReadWrite) { @@ -591,8 +595,14 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s return ERR_INVALID_HANDLE; } - return shared_memory->Map(Core::CurrentProcess(), addr, permissions_type, - MemoryPermission::DontCare); + auto* const current_process = Core::CurrentProcess(); + const auto& vm_manager = current_process->VMManager(); + + if (!vm_manager.IsWithinASLRRegion(addr, size)) { + return ERR_INVALID_MEMORY_RANGE; + } + + return shared_memory->Map(current_process, addr, permissions_type, MemoryPermission::DontCare); } static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size) { @@ -607,10 +617,24 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 return ERR_INVALID_SIZE; } + if (!IsValidAddressRange(addr, size)) { + return ERR_INVALID_ADDRESS_STATE; + } + auto& kernel = Core::System::GetInstance().Kernel(); auto shared_memory = kernel.HandleTable().Get(shared_memory_handle); + if (!shared_memory) { + return ERR_INVALID_HANDLE; + } + + auto* const current_process = Core::CurrentProcess(); + const auto& vm_manager = current_process->VMManager(); + + if (!vm_manager.IsWithinASLRRegion(addr, size)) { + return ERR_INVALID_MEMORY_RANGE; + } - return shared_memory->Unmap(Core::CurrentProcess(), addr); + return shared_memory->Unmap(current_process, addr); } /// Query process memory diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 1e28ccbda..e1a34eef1 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -507,6 +507,26 @@ u64 VMManager::GetASLRRegionSize() const { return aslr_region_end - aslr_region_base; } +bool VMManager::IsWithinASLRRegion(VAddr begin, u64 size) const { + const VAddr range_end = begin + size; + const VAddr aslr_start = GetASLRRegionBaseAddress(); + const VAddr aslr_end = GetASLRRegionEndAddress(); + + if (aslr_start > begin || begin > range_end || range_end - 1 > aslr_end - 1) { + return false; + } + + if (range_end > heap_region_base && heap_region_end > begin) { + return false; + } + + if (range_end > map_region_base && map_region_end > begin) { + return false; + } + + return true; +} + VAddr VMManager::GetCodeRegionBaseAddress() const { return code_region_base; } diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 4accde6b3..84c890224 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -211,6 +211,9 @@ public: /// Gets the end address of the ASLR region. VAddr GetASLRRegionEndAddress() const; + /// Determines whether or not the specified address range is within the ASLR region. + bool IsWithinASLRRegion(VAddr address, u64 size) const; + /// Gets the size of the ASLR region u64 GetASLRRegionSize() const; -- cgit v1.2.3