summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/kernel/svc.cpp30
-rw-r--r--src/core/hle/kernel/vm_manager.cpp20
-rw-r--r--src/core/hle/kernel/vm_manager.h3
3 files changed, 50 insertions, 3 deletions
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<MemoryPermission>(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<SharedMemory>(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;