From 0a1465f198aa9a95930023453f960fada37a5a07 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 1 Dec 2020 17:14:23 -0800 Subject: [PATCH] kern: add new overflow checks on KMemoryRegions --- .../include/mesosphere/kern_k_memory_layout.hpp | 4 +++- .../include/mesosphere/kern_k_memory_region.hpp | 1 + .../board/nintendo/nx/kern_k_system_control.cpp | 8 ++++++++ .../source/kern_k_memory_layout.board.nintendo_nx.cpp | 2 ++ .../libmesosphere/source/kern_k_page_table_base.cpp | 3 +++ libraries/libmesosphere/source/kern_k_thread.cpp | 1 + libraries/libmesosphere/source/kern_main.cpp | 11 +++++++++++ .../source/svc/kern_svc_address_translation.cpp | 3 +++ 8 files changed, 32 insertions(+), 1 deletion(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_layout.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_layout.hpp index 88aa69f0a..a6148292f 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_layout.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_layout.hpp @@ -112,7 +112,9 @@ namespace ams::kern { } static ALWAYS_INLINE KVirtualAddress GetStackTopAddress(s32 core_id, KMemoryRegionType type) { - return Dereference(GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast(core_id))).GetEndAddress(); + const auto ®ion = Dereference(GetVirtualMemoryRegionTree().FindByTypeAndAttribute(type, static_cast(core_id))); + MESOSPHERE_INIT_ABORT_UNLESS(region.GetEndAddress() != 0); + return region.GetEndAddress(); } public: static ALWAYS_INLINE KMemoryRegionTree &GetVirtualMemoryRegionTree() { return s_virtual_tree; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_region.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_region.hpp index 63ff1c239..af88139e7 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_region.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_region.hpp @@ -93,6 +93,7 @@ namespace ams::kern { } constexpr ALWAYS_INLINE bool Contains(uintptr_t address) const { + MESOSPHERE_INIT_ABORT_UNLESS(this->GetEndAddress() != 0); return this->GetAddress() <= address && address <= this->GetLastAddress(); } diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp index 5024082e7..a3068d655 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_system_control.cpp @@ -182,6 +182,9 @@ namespace ams::kern::board::nintendo::nx { const KMemoryRegion *region = KMemoryLayout::Find(KPhysicalAddress(address)); if (AMS_LIKELY(region != nullptr)) { if (AMS_LIKELY(region->IsDerivedFrom(KMemoryRegionType_MemoryController))) { + /* Check the region is valid. */ + MESOSPHERE_ABORT_UNLESS(region->GetEndAddress() != 0); + /* Get the offset within the region. */ const size_t offset = address - region->GetAddress(); MESOSPHERE_ABORT_UNLESS(offset < region->GetSize()); @@ -210,6 +213,9 @@ namespace ams::kern::board::nintendo::nx { region->IsDerivedFrom(KMemoryRegionType_MemoryController0) || region->IsDerivedFrom(KMemoryRegionType_MemoryController1)) { + /* Check the region is valid. */ + MESOSPHERE_ABORT_UNLESS(region->GetEndAddress() != 0); + /* Get the offset within the region. */ const size_t offset = address - region->GetAddress(); MESOSPHERE_ABORT_UNLESS(offset < region->GetSize()); @@ -449,6 +455,8 @@ namespace ams::kern::board::nintendo::nx { /* Configure the Kernel Carveout region. */ { const auto carveout = KMemoryLayout::GetCarveoutRegionExtents(); + MESOSPHERE_ABORT_UNLESS(carveout.GetEndAddress() != 0); + smc::ConfigureCarveout(0, carveout.GetAddress(), carveout.GetSize()); } diff --git a/libraries/libmesosphere/source/kern_k_memory_layout.board.nintendo_nx.cpp b/libraries/libmesosphere/source/kern_k_memory_layout.board.nintendo_nx.cpp index d3a98cc62..8c051a15c 100644 --- a/libraries/libmesosphere/source/kern_k_memory_layout.board.nintendo_nx.cpp +++ b/libraries/libmesosphere/source/kern_k_memory_layout.board.nintendo_nx.cpp @@ -55,6 +55,7 @@ namespace ams::kern { MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(start, size, phys_type, attr)); const KMemoryRegion *phys = KMemoryLayout::GetPhysicalMemoryRegionTree().FindByTypeAndAttribute(phys_type, attr); MESOSPHERE_INIT_ABORT_UNLESS(phys != nullptr); + MESOSPHERE_INIT_ABORT_UNLESS(phys->GetEndAddress() != 0); MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetVirtualMemoryRegionTree().Insert(phys->GetPairAddress(), size, virt_type, attr)); } @@ -104,6 +105,7 @@ namespace ams::kern { void SetupPoolPartitionMemoryRegions() { /* Start by identifying the extents of the DRAM memory region. */ const auto dram_extents = KMemoryLayout::GetMainMemoryPhysicalExtents(); + MESOSPHERE_INIT_ABORT_UNLESS(dram_extents.GetEndAddress() != 0); /* Determine the end of the pool region. */ const uintptr_t pool_end = dram_extents.GetEndAddress() - KTraceBufferSize; diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index a28938593..b505019e9 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -1807,6 +1807,9 @@ namespace ams::kern { const KMemoryRegion *region = KMemoryLayout::GetPhysicalMemoryRegionTree().FindFirstDerived(region_type); R_UNLESS(region != nullptr, svc::ResultOutOfRange()); + /* Check that the region is valid. */ + MESOSPHERE_ABORT_UNLESS(region->GetEndAddress() != 0); + /* Map the region. */ R_TRY_CATCH(this->MapStatic(region->GetAddress(), region->GetSize(), perm)) { R_CONVERT(svc::ResultInvalidAddress, svc::ResultOutOfRange()) diff --git a/libraries/libmesosphere/source/kern_k_thread.cpp b/libraries/libmesosphere/source/kern_k_thread.cpp index 1e2f7e581..600c7f4cd 100644 --- a/libraries/libmesosphere/source/kern_k_thread.cpp +++ b/libraries/libmesosphere/source/kern_k_thread.cpp @@ -207,6 +207,7 @@ namespace ams::kern { Result KThread::InitializeThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner, ThreadType type) { /* Get stack region for the thread. */ const auto &stack_region = KMemoryLayout::GetKernelStackRegion(); + MESOSPHERE_ABORT_UNLESS(stack_region.GetEndAddress() != 0); /* Allocate a page to use as the thread. */ KPageBuffer *page = KPageBuffer::Allocate(); diff --git a/libraries/libmesosphere/source/kern_main.cpp b/libraries/libmesosphere/source/kern_main.cpp index e481b8f6b..5ee230a41 100644 --- a/libraries/libmesosphere/source/kern_main.cpp +++ b/libraries/libmesosphere/source/kern_main.cpp @@ -52,6 +52,8 @@ namespace ams::kern { /* Initialize the memory manager and the KPageBuffer slabheap. */ { const auto &management_region = KMemoryLayout::GetPoolManagementRegion(); + MESOSPHERE_ABORT_UNLESS(management_region.GetEndAddress() != 0); + Kernel::GetMemoryManager().Initialize(management_region.GetAddress(), management_region.GetSize()); init::InitializeKPageBufferSlabHeap(); } @@ -68,6 +70,8 @@ namespace ams::kern { /* Initialize the Dynamic Slab Heaps. */ { const auto &pt_heap_region = KMemoryLayout::GetPageTableHeapRegion(); + MESOSPHERE_ABORT_UNLESS(pt_heap_region.GetEndAddress() != 0); + Kernel::InitializeResourceManagers(pt_heap_region.GetAddress(), pt_heap_region.GetSize()); } } @@ -124,6 +128,13 @@ namespace ams::kern { /* Resume all threads suspended while we initialized. */ KThread::ResumeThreadsSuspendedForInit(); + + /* Validate that all reserved dram blocks are valid. */ + for (const auto ®ion : KMemoryLayout::GetPhysicalMemoryRegionTree()) { + if (region.IsDerivedFrom(KMemoryRegionType_DramReservedBase)) { + MESOSPHERE_ABORT_UNLESS(region.GetEndAddress() != 0); + } + } } cpu::SynchronizeAllCores(); diff --git a/libraries/libmesosphere/source/svc/kern_svc_address_translation.cpp b/libraries/libmesosphere/source/svc/kern_svc_address_translation.cpp index 80e161171..4fb32996c 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_address_translation.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_address_translation.cpp @@ -92,6 +92,9 @@ namespace ams::kern::svc { /* Ensure that we found the region. */ R_UNLESS(region != nullptr, svc::ResultNotFound()); + /* Chcek that the region is valid. */ + MESOSPHERE_ABORT_UNLESS(region->GetEndAddress() != 0); + R_TRY(pt.QueryStaticMapping(std::addressof(found_address), region->GetAddress(), region->GetSize())); found_size = region->GetSize(); }