From 0be8fffc992e30da42004b4e640b7095e1040f53 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 4 Mar 2019 16:30:17 -0500 Subject: svc: Migrate address range checking functions to VMManager Provides a bit of a more proper interface for these functions. --- src/core/hle/kernel/svc.cpp | 25 ++++--------------------- src/core/hle/kernel/vm_manager.cpp | 22 ++++++++++++++++++++-- src/core/hle/kernel/vm_manager.h | 6 ++++++ 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index c5d399bab..223d717e2 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -47,23 +47,6 @@ constexpr bool IsValidAddressRange(VAddr address, u64 size) { return address + size > address; } -// Checks if a given address range lies within a larger address range. -constexpr bool IsInsideAddressRange(VAddr address, u64 size, VAddr address_range_begin, - VAddr address_range_end) { - const VAddr end_address = address + size - 1; - return address_range_begin <= address && end_address <= address_range_end - 1; -} - -bool IsInsideAddressSpace(const VMManager& vm, VAddr address, u64 size) { - return IsInsideAddressRange(address, size, vm.GetAddressSpaceBaseAddress(), - vm.GetAddressSpaceEndAddress()); -} - -bool IsInsideNewMapRegion(const VMManager& vm, VAddr address, u64 size) { - return IsInsideAddressRange(address, size, vm.GetNewMapRegionBaseAddress(), - vm.GetNewMapRegionEndAddress()); -} - // 8 GiB constexpr u64 MAIN_MEMORY_SIZE = 0x200000000; @@ -105,14 +88,14 @@ ResultCode MapUnmapMemorySanityChecks(const VMManager& vm_manager, VAddr dst_add return ERR_INVALID_ADDRESS_STATE; } - if (!IsInsideAddressSpace(vm_manager, src_addr, size)) { + if (!vm_manager.IsWithinAddressSpace(src_addr, size)) { LOG_ERROR(Kernel_SVC, "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", src_addr, size); return ERR_INVALID_ADDRESS_STATE; } - if (!IsInsideNewMapRegion(vm_manager, dst_addr, size)) { + if (!vm_manager.IsWithinNewMapRegion(dst_addr, size)) { LOG_ERROR(Kernel_SVC, "Destination is not within the new map region, addr=0x{:016X}, size=0x{:016X}", dst_addr, size); @@ -238,7 +221,7 @@ static ResultCode SetMemoryPermission(VAddr addr, u64 size, u32 prot) { auto* const current_process = Core::CurrentProcess(); auto& vm_manager = current_process->VMManager(); - if (!IsInsideAddressSpace(vm_manager, addr, size)) { + if (!vm_manager.IsWithinAddressSpace(addr, size)) { LOG_ERROR(Kernel_SVC, "Source is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr, size); @@ -299,7 +282,7 @@ static ResultCode SetMemoryAttribute(VAddr address, u64 size, u32 mask, u32 attr } auto& vm_manager = Core::CurrentProcess()->VMManager(); - if (!IsInsideAddressSpace(vm_manager, address, size)) { + if (!vm_manager.IsWithinAddressSpace(address, size)) { LOG_ERROR(Kernel_SVC, "Given address (0x{:016X}) is outside the bounds of the address space.", address); return ERR_INVALID_ADDRESS_STATE; diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 10ad94aa6..56f3d1f79 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -17,8 +17,8 @@ #include "core/memory_setup.h" namespace Kernel { - -static const char* GetMemoryStateName(MemoryState state) { +namespace { +const char* GetMemoryStateName(MemoryState state) { static constexpr const char* names[] = { "Unmapped", "Io", "Normal", "CodeStatic", @@ -35,6 +35,14 @@ static const char* GetMemoryStateName(MemoryState state) { return names[ToSvcMemoryState(state)]; } +// Checks if a given address range lies within a larger address range. +constexpr bool IsInsideAddressRange(VAddr address, u64 size, VAddr address_range_begin, + VAddr address_range_end) { + const VAddr end_address = address + size - 1; + return address_range_begin <= address && end_address <= address_range_end - 1; +} +} // Anonymous namespace + bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { ASSERT(base + size == next.base); if (permissions != next.permissions || state != next.state || attribute != next.attribute || @@ -706,6 +714,11 @@ u64 VMManager::GetAddressSpaceWidth() const { return address_space_width; } +bool VMManager::IsWithinAddressSpace(VAddr address, u64 size) const { + return IsInsideAddressRange(address, size, GetAddressSpaceBaseAddress(), + GetAddressSpaceEndAddress()); +} + VAddr VMManager::GetASLRRegionBaseAddress() const { return aslr_region_base; } @@ -786,6 +799,11 @@ u64 VMManager::GetNewMapRegionSize() const { return new_map_region_end - new_map_region_base; } +bool VMManager::IsWithinNewMapRegion(VAddr address, u64 size) const { + return IsInsideAddressRange(address, size, GetNewMapRegionBaseAddress(), + GetNewMapRegionEndAddress()); +} + VAddr VMManager::GetTLSIORegionBaseAddress() const { return tls_io_region_base; } diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 6091533bc..60f36a5b9 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -432,6 +432,9 @@ public: /// Gets the address space width in bits. u64 GetAddressSpaceWidth() const; + /// Determines whether or not the given address range lies within the address space. + bool IsWithinAddressSpace(VAddr address, u64 size) const; + /// Gets the base address of the ASLR region. VAddr GetASLRRegionBaseAddress() const; @@ -480,6 +483,9 @@ public: /// Gets the total size of the new map region in bytes. u64 GetNewMapRegionSize() const; + /// Determines whether or not the given address range lies within the new map region + bool IsWithinNewMapRegion(VAddr address, u64 size) const; + /// Gets the base address of the TLS IO region. VAddr GetTLSIORegionBaseAddress() const; -- cgit v1.2.3 From 6c42a23550de8d6181562e969a142004f91c7daf Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 4 Mar 2019 16:40:17 -0500 Subject: vm_manager: Provide address range checking functions for other memory regions Makes the interface uniform when it comes to checking various memory regions. --- src/core/hle/kernel/vm_manager.cpp | 19 +++++++++++++++++++ src/core/hle/kernel/vm_manager.h | 20 ++++++++++++++++---- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 56f3d1f79..e81856bdc 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -763,6 +763,11 @@ u64 VMManager::GetCodeRegionSize() const { return code_region_end - code_region_base; } +bool VMManager::IsWithinCodeRegion(VAddr address, u64 size) const { + return IsInsideAddressRange(address, size, GetCodeRegionBaseAddress(), + GetCodeRegionEndAddress()); +} + VAddr VMManager::GetHeapRegionBaseAddress() const { return heap_region_base; } @@ -775,6 +780,11 @@ u64 VMManager::GetHeapRegionSize() const { return heap_region_end - heap_region_base; } +bool VMManager::IsWithinHeapRegion(VAddr address, u64 size) const { + return IsInsideAddressRange(address, size, GetHeapRegionBaseAddress(), + GetHeapRegionEndAddress()); +} + VAddr VMManager::GetMapRegionBaseAddress() const { return map_region_base; } @@ -787,6 +797,10 @@ u64 VMManager::GetMapRegionSize() const { return map_region_end - map_region_base; } +bool VMManager::IsWithinMapRegion(VAddr address, u64 size) const { + return IsInsideAddressRange(address, size, GetMapRegionBaseAddress(), GetMapRegionEndAddress()); +} + VAddr VMManager::GetNewMapRegionBaseAddress() const { return new_map_region_base; } @@ -816,4 +830,9 @@ u64 VMManager::GetTLSIORegionSize() const { return tls_io_region_end - tls_io_region_base; } +bool VMManager::IsWithinTLSIORegion(VAddr address, u64 size) const { + return IsInsideAddressRange(address, size, GetTLSIORegionBaseAddress(), + GetTLSIORegionEndAddress()); +} + } // namespace Kernel diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 60f36a5b9..88e0b3c02 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -441,12 +441,12 @@ 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; + /// Determines whether or not the specified address range is within the ASLR region. + bool IsWithinASLRRegion(VAddr address, u64 size) const; + /// Gets the base address of the code region. VAddr GetCodeRegionBaseAddress() const; @@ -456,6 +456,9 @@ public: /// Gets the total size of the code region in bytes. u64 GetCodeRegionSize() const; + /// Determines whether or not the specified range is within the code region. + bool IsWithinCodeRegion(VAddr address, u64 size) const; + /// Gets the base address of the heap region. VAddr GetHeapRegionBaseAddress() const; @@ -465,6 +468,9 @@ public: /// Gets the total size of the heap region in bytes. u64 GetHeapRegionSize() const; + /// Determines whether or not the specified range is within the heap region. + bool IsWithinHeapRegion(VAddr address, u64 size) const; + /// Gets the base address of the map region. VAddr GetMapRegionBaseAddress() const; @@ -474,6 +480,9 @@ public: /// Gets the total size of the map region in bytes. u64 GetMapRegionSize() const; + /// Determines whether or not the specified range is within the map region. + bool IsWithinMapRegion(VAddr address, u64 size) const; + /// Gets the base address of the new map region. VAddr GetNewMapRegionBaseAddress() const; @@ -483,7 +492,7 @@ public: /// Gets the total size of the new map region in bytes. u64 GetNewMapRegionSize() const; - /// Determines whether or not the given address range lies within the new map region + /// Determines whether or not the given address range is within the new map region bool IsWithinNewMapRegion(VAddr address, u64 size) const; /// Gets the base address of the TLS IO region. @@ -495,6 +504,9 @@ public: /// Gets the total size of the TLS IO region in bytes. u64 GetTLSIORegionSize() const; + /// Determines if the given address range is within the TLS IO region. + bool IsWithinTLSIORegion(VAddr address, u64 size) const; + /// Each VMManager has its own page table, which is set as the main one when the owning process /// is scheduled. Memory::PageTable page_table; -- cgit v1.2.3 From 40de7f6fe86358e76244ed14c33752b4b9cd0cf0 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 4 Mar 2019 17:16:47 -0500 Subject: vm_manager: Use range helpers in HeapAlloc() and HeapFree() Significantly tidies up two guard conditionals. --- src/core/hle/kernel/vm_manager.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index e81856bdc..05c59af34 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -257,8 +257,7 @@ ResultCode VMManager::ReprotectRange(VAddr target, u64 size, VMAPermission new_p } ResultVal VMManager::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { - if (target < GetHeapRegionBaseAddress() || target + size > GetHeapRegionEndAddress() || - target + size < target) { + if (!IsWithinHeapRegion(target, size)) { return ERR_INVALID_ADDRESS; } @@ -293,8 +292,7 @@ ResultVal VMManager::HeapAllocate(VAddr target, u64 size, VMAPermission p } ResultCode VMManager::HeapFree(VAddr target, u64 size) { - if (target < GetHeapRegionBaseAddress() || target + size > GetHeapRegionEndAddress() || - target + size < target) { + if (!IsWithinHeapRegion(target, size)) { return ERR_INVALID_ADDRESS; } -- cgit v1.2.3