From 70bf8330701dc9147fc88cb7c72d026885d7cde7 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 9 Oct 2024 12:03:21 -0700 Subject: [PATCH] kern: KAddressSpaceInfo now takes CreateProcessFlags in getters --- .../mesosphere/kern_k_address_space_info.hpp | 4 +-- .../source/kern_k_address_space_info.cpp | 26 +++++++++++--- .../source/kern_k_initial_process_reader.cpp | 35 ++++++++++--------- .../source/kern_k_page_table_base.cpp | 4 +-- .../source/svc/kern_svc_process.cpp | 14 ++++---- 5 files changed, 52 insertions(+), 31 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp index 9e20dd254..8af8404cc 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_address_space_info.hpp @@ -37,8 +37,8 @@ namespace ams::kern { size_t m_size; Type m_type; public: - static uintptr_t GetAddressSpaceStart(size_t width, Type type); - static size_t GetAddressSpaceSize(size_t width, Type type); + static uintptr_t GetAddressSpaceStart(ams::svc::CreateProcessFlag flags, Type type); + static size_t GetAddressSpaceSize(ams::svc::CreateProcessFlag flags, Type type); static void SetAddressSpaceSize(size_t width, Type type, size_t size); diff --git a/libraries/libmesosphere/source/kern_k_address_space_info.cpp b/libraries/libmesosphere/source/kern_k_address_space_info.cpp index ef585eba8..b23f6e929 100644 --- a/libraries/libmesosphere/source/kern_k_address_space_info.cpp +++ b/libraries/libmesosphere/source/kern_k_address_space_info.cpp @@ -37,6 +37,24 @@ namespace ams::kern { { 39, Invalid, ams::svc::AddressMemoryRegionStack39Size, KAddressSpaceInfo::Type_Stack, }, }; + constexpr u8 FlagsToAddressSpaceWidthTable[4] = { + 32, 36, 32, 39 + }; + + constexpr size_t GetAddressSpaceWidth(ams::svc::CreateProcessFlag flags) { + /* Convert the input flags to an array index. */ + const size_t idx = (flags & ams::svc::CreateProcessFlag_AddressSpaceMask) >> ams::svc::CreateProcessFlag_AddressSpaceShift; + MESOSPHERE_ABORT_UNLESS(idx < sizeof(FlagsToAddressSpaceWidthTable)); + + /* Return the width. */ + return FlagsToAddressSpaceWidthTable[idx]; + } + + static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace32Bit) == 32); + static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated) == 36); + static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias) == 32); + static_assert(GetAddressSpaceWidth(ams::svc::CreateProcessFlag_AddressSpace64Bit) == 39); + KAddressSpaceInfo &GetAddressSpaceInfo(size_t width, KAddressSpaceInfo::Type type) { for (auto &info : AddressSpaceInfos) { if (info.GetWidth() == width && info.GetType() == type) { @@ -48,12 +66,12 @@ namespace ams::kern { } - uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(size_t width, KAddressSpaceInfo::Type type) { - return GetAddressSpaceInfo(width, type).GetAddress(); + uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(ams::svc::CreateProcessFlag flags, KAddressSpaceInfo::Type type) { + return GetAddressSpaceInfo(GetAddressSpaceWidth(flags), type).GetAddress(); } - size_t KAddressSpaceInfo::GetAddressSpaceSize(size_t width, KAddressSpaceInfo::Type type) { - return GetAddressSpaceInfo(width, type).GetSize(); + size_t KAddressSpaceInfo::GetAddressSpaceSize(ams::svc::CreateProcessFlag flags, KAddressSpaceInfo::Type type) { + return GetAddressSpaceInfo(GetAddressSpaceWidth(flags), type).GetSize(); } void KAddressSpaceInfo::SetAddressSpaceSize(size_t width, Type type, size_t size) { diff --git a/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp b/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp index c5ef13ac5..9c91889f9 100644 --- a/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp +++ b/libraries/libmesosphere/source/kern_k_initial_process_reader.cpp @@ -193,40 +193,25 @@ namespace ams::kern { R_UNLESS(this->Is64Bit(), svc::ResultInvalidCombination()); } - using ASType = KAddressSpaceInfo::Type; - const uintptr_t start_address = rx_address; const uintptr_t end_address = bss_size > 0 ? bss_address + bss_size : rw_address + rw_size; - const size_t as_width = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? 39 : 36) : 32; - const ASType as_type = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? KAddressSpaceInfo::Type_Map39Bit : KAddressSpaceInfo::Type_MapSmall) : KAddressSpaceInfo::Type_MapSmall; - const uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(as_width, as_type); - const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(as_width, as_type); - const uintptr_t map_end = map_start + map_size; MESOSPHERE_ABORT_UNLESS(start_address == 0); /* Default fields in parameter to zero. */ *out = {}; /* Set fields in parameter. */ - out->code_address = map_start + start_address; + out->code_address = 0; out->code_num_pages = util::AlignUp(end_address - start_address, PageSize) / PageSize; out->program_id = m_kip_header.GetProgramId(); out->version = m_kip_header.GetVersion(); out->flags = 0; out->reslimit = ams::svc::InvalidHandle; out->system_resource_num_pages = 0; - MESOSPHERE_ABORT_UNLESS((out->code_address / PageSize) + out->code_num_pages <= (map_end / PageSize)); /* Copy name field. */ m_kip_header.GetName(out->name, sizeof(out->name)); - /* Apply ASLR, if needed. */ - if (enable_aslr) { - const size_t choices = (map_end / KernelAslrAlignment) - (util::AlignUp(out->code_address + out->code_num_pages * PageSize, KernelAslrAlignment) / KernelAslrAlignment); - out->code_address += KSystemControl::GenerateRandomRange(0, choices) * KernelAslrAlignment; - out->flags |= ams::svc::CreateProcessFlag_EnableAslr; - } - /* Apply other flags. */ if (this->Is64Bit()) { out->flags |= ams::svc::CreateProcessFlag_Is64Bit; @@ -236,10 +221,28 @@ namespace ams::kern { } else { out->flags |= ams::svc::CreateProcessFlag_AddressSpace32Bit; } + if (enable_aslr) { + out->flags |= ams::svc::CreateProcessFlag_EnableAslr; + } /* All initial processes should disable device address space merge. */ out->flags |= ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge; + /* Set and check code address. */ + using ASType = KAddressSpaceInfo::Type; + const ASType as_type = this->Is64BitAddressSpace() ? ((GetTargetFirmware() >= TargetFirmware_2_0_0) ? KAddressSpaceInfo::Type_Map39Bit : KAddressSpaceInfo::Type_MapSmall) : KAddressSpaceInfo::Type_MapSmall; + const uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(out->flags), as_type); + const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(out->flags), as_type); + const uintptr_t map_end = map_start + map_size; + out->code_address = map_start + start_address; + MESOSPHERE_ABORT_UNLESS((out->code_address / PageSize) + out->code_num_pages <= (map_end / PageSize)); + + /* Apply ASLR, if needed. */ + if (enable_aslr) { + const size_t choices = (map_end / KernelAslrAlignment) - (util::AlignUp(out->code_address + out->code_num_pages * PageSize, KernelAslrAlignment) / KernelAslrAlignment); + out->code_address += KSystemControl::GenerateRandomRange(0, choices) * KernelAslrAlignment; + } + R_SUCCEED(); } diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 2e90d924e..613dc0dbb 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -141,10 +141,10 @@ namespace ams::kern { /* Define helpers. */ auto GetSpaceStart = [&](KAddressSpaceInfo::Type type) ALWAYS_INLINE_LAMBDA { - return KAddressSpaceInfo::GetAddressSpaceStart(m_address_space_width, type); + return KAddressSpaceInfo::GetAddressSpaceStart(flags, type); }; auto GetSpaceSize = [&](KAddressSpaceInfo::Type type) ALWAYS_INLINE_LAMBDA { - return KAddressSpaceInfo::GetAddressSpaceSize(m_address_space_width, type); + return KAddressSpaceInfo::GetAddressSpaceSize(flags, type); }; /* Default to zero alias region extra size. */ diff --git a/libraries/libmesosphere/source/svc/kern_svc_process.cpp b/libraries/libmesosphere/source/svc/kern_svc_process.cpp index 76e36302b..5141a2c31 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_process.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_process.cpp @@ -110,8 +110,8 @@ namespace ams::kern::svc { case ams::svc::CreateProcessFlag_AddressSpace32Bit: case ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias: { - map_start = KAddressSpaceInfo::GetAddressSpaceStart(32, KAddressSpaceInfo::Type_MapSmall); - map_size = KAddressSpaceInfo::GetAddressSpaceSize(32, KAddressSpaceInfo::Type_MapSmall); + map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall); + map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall); map_end = map_start + map_size; } break; @@ -120,8 +120,8 @@ namespace ams::kern::svc { /* 64-bit address space requires 64-bit process. */ R_UNLESS(is_64_bit, svc::ResultInvalidCombination()); - map_start = KAddressSpaceInfo::GetAddressSpaceStart(36, KAddressSpaceInfo::Type_MapSmall); - map_size = KAddressSpaceInfo::GetAddressSpaceSize(36, KAddressSpaceInfo::Type_MapSmall); + map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall); + map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_MapSmall); map_end = map_start + map_size; } break; @@ -130,10 +130,10 @@ namespace ams::kern::svc { /* 64-bit address space requires 64-bit process. */ R_UNLESS(is_64_bit, svc::ResultInvalidCombination()); - map_start = KAddressSpaceInfo::GetAddressSpaceStart(39, KAddressSpaceInfo::Type_Map39Bit); - map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(39, KAddressSpaceInfo::Type_Map39Bit); + map_start = KAddressSpaceInfo::GetAddressSpaceStart(static_cast(params.flags), KAddressSpaceInfo::Type_Map39Bit); + map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_Map39Bit); - map_size = KAddressSpaceInfo::GetAddressSpaceSize(39, KAddressSpaceInfo::Type_Heap); + map_size = KAddressSpaceInfo::GetAddressSpaceSize(static_cast(params.flags), KAddressSpaceInfo::Type_Heap); } break; default: