1
0
Fork 0
forked from suyu/suyu

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.
This commit is contained in:
Lioncash 2018-10-17 22:39:21 -04:00
parent 7dee60d7d2
commit 33830aa65a
3 changed files with 50 additions and 3 deletions

View file

@ -578,6 +578,10 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
return ERR_INVALID_SIZE; return ERR_INVALID_SIZE;
} }
if (!IsValidAddressRange(addr, size)) {
return ERR_INVALID_ADDRESS_STATE;
}
const auto permissions_type = static_cast<MemoryPermission>(permissions); const auto permissions_type = static_cast<MemoryPermission>(permissions);
if (permissions_type != MemoryPermission::Read && if (permissions_type != MemoryPermission::Read &&
permissions_type != MemoryPermission::ReadWrite) { permissions_type != MemoryPermission::ReadWrite) {
@ -591,8 +595,14 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
} }
return shared_memory->Map(Core::CurrentProcess(), addr, permissions_type, auto* const current_process = Core::CurrentProcess();
MemoryPermission::DontCare); 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) { 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; return ERR_INVALID_SIZE;
} }
if (!IsValidAddressRange(addr, size)) {
return ERR_INVALID_ADDRESS_STATE;
}
auto& kernel = Core::System::GetInstance().Kernel(); auto& kernel = Core::System::GetInstance().Kernel();
auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle); auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);
if (!shared_memory) {
return ERR_INVALID_HANDLE;
}
return shared_memory->Unmap(Core::CurrentProcess(), addr); 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(current_process, addr);
} }
/// Query process memory /// Query process memory

View file

@ -507,6 +507,26 @@ u64 VMManager::GetASLRRegionSize() const {
return aslr_region_end - aslr_region_base; 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 { VAddr VMManager::GetCodeRegionBaseAddress() const {
return code_region_base; return code_region_base;
} }

View file

@ -211,6 +211,9 @@ public:
/// Gets the end address of the ASLR region. /// Gets the end address of the ASLR region.
VAddr GetASLRRegionEndAddress() const; 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 /// Gets the size of the ASLR region
u64 GetASLRRegionSize() const; u64 GetASLRRegionSize() const;