From 2f930c2d5fc017c3afcb15f9f5c1c25f6bd1656b Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 7 Apr 2021 08:23:21 -0700 Subject: [PATCH] kern: support immortal processes --- .../kern_k_initial_process_reader.hpp | 2 + .../include/mesosphere/kern_k_process.hpp | 3 +- .../source/kern_initial_process.cpp | 2 +- .../libmesosphere/source/kern_k_process.cpp | 37 +++++++++++-------- 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_initial_process_reader.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_initial_process_reader.hpp index db3d58e6b..ce534533f 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_initial_process_reader.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_initial_process_reader.hpp @@ -70,6 +70,7 @@ namespace ams::kern { constexpr bool Is64Bit() const { return (m_flags & (1 << 3)); } constexpr bool Is64BitAddressSpace() const { return (m_flags & (1 << 4)); } constexpr bool UsesSecureMemory() const { return (m_flags & (1 << 5)); } + constexpr bool IsImmortal() const { return (m_flags & (1 << 6)); } constexpr u32 GetRxAddress() const { return m_rx_address; } constexpr u32 GetRxSize() const { return m_rx_size; } @@ -117,6 +118,7 @@ namespace ams::kern { constexpr bool Is64Bit() const { return m_kip_header->Is64Bit(); } constexpr bool Is64BitAddressSpace() const { return m_kip_header->Is64BitAddressSpace(); } constexpr bool UsesSecureMemory() const { return m_kip_header->UsesSecureMemory(); } + constexpr bool IsImmortal() const { return m_kip_header->IsImmortal(); } bool Attach(u8 *bin) { if (KInitialProcessHeader *header = reinterpret_cast(bin); header->IsValid()) { diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index c2d50acdf..1706a0721 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -98,6 +98,7 @@ namespace ams::kern { SharedMemoryInfoList m_shared_memory_list{}; BetaList m_beta_list{}; bool m_is_suspended{}; + bool m_is_immortal{}; bool m_is_jit_debug{}; ams::svc::DebugEvent m_jit_debug_event_type{}; ams::svc::DebugException m_jit_debug_exception_type{}; @@ -143,7 +144,7 @@ namespace ams::kern { KProcess() { /* ... */ } virtual ~KProcess() { /* ... */ } - Result Initialize(const ams::svc::CreateProcessParameter ¶ms, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool); + Result Initialize(const ams::svc::CreateProcessParameter ¶ms, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool, bool immortal); Result Initialize(const ams::svc::CreateProcessParameter ¶ms, svc::KUserPointer caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool); void Exit(); diff --git a/libraries/libmesosphere/source/kern_initial_process.cpp b/libraries/libmesosphere/source/kern_initial_process.cpp index be962d668..24616fbb6 100644 --- a/libraries/libmesosphere/source/kern_initial_process.cpp +++ b/libraries/libmesosphere/source/kern_initial_process.cpp @@ -118,7 +118,7 @@ namespace ams::kern { MESOSPHERE_ABORT_UNLESS(new_process != nullptr); /* Initialize the process. */ - MESOSPHERE_R_ABORT_UNLESS(new_process->Initialize(params, pg, reader.GetCapabilities(), reader.GetNumCapabilities(), std::addressof(Kernel::GetSystemResourceLimit()), pool)); + MESOSPHERE_R_ABORT_UNLESS(new_process->Initialize(params, pg, reader.GetCapabilities(), reader.GetNumCapabilities(), std::addressof(Kernel::GetSystemResourceLimit()), pool, reader.IsImmortal())); } } diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index 6aaaefa8f..474f08c7f 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -231,7 +231,7 @@ namespace ams::kern { return ResultSuccess(); } - Result KProcess::Initialize(const ams::svc::CreateProcessParameter ¶ms, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool) { + Result KProcess::Initialize(const ams::svc::CreateProcessParameter ¶ms, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool, bool immortal) { MESOSPHERE_ASSERT_THIS(); MESOSPHERE_ASSERT(res_limit != nullptr); MESOSPHERE_ABORT_UNLESS((params.code_num_pages * PageSize) / PageSize == static_cast(params.code_num_pages)); @@ -241,6 +241,7 @@ namespace ams::kern { m_resource_limit = res_limit; m_system_resource_address = Null; m_system_resource_num_pages = 0; + m_is_immortal = immortal; /* Setup page table. */ /* NOTE: Nintendo passes process ID despite not having set it yet. */ @@ -289,6 +290,7 @@ namespace ams::kern { /* Set pool and resource limit. */ m_memory_pool = pool; m_resource_limit = res_limit; + m_is_immortal = false; /* Get the memory sizes. */ const size_t code_num_pages = params.code_num_pages; @@ -406,9 +408,11 @@ namespace ams::kern { } Result KProcess::StartTermination() { - /* Finalize the handle table, when we're done. */ + /* Finalize the handle table when we're done, if the process isn't immortal. */ ON_SCOPE_EXIT { - m_handle_table.Finalize(); + if (!m_is_immortal) { + m_handle_table.Finalize(); + } }; /* Terminate child threads other than the current one. */ @@ -416,20 +420,23 @@ namespace ams::kern { } void KProcess::FinishTermination() { - /* Release resource limit hint. */ - if (m_resource_limit != nullptr) { - m_memory_release_hint = this->GetUsedUserPhysicalMemorySize(); - m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, 0, m_memory_release_hint); - } + /* Only allow termination to occur if the process isn't immortal. */ + if (!m_is_immortal) { + /* Release resource limit hint. */ + if (m_resource_limit != nullptr) { + m_memory_release_hint = this->GetUsedUserPhysicalMemorySize(); + m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, 0, m_memory_release_hint); + } - /* Change state. */ - { - KScopedSchedulerLock sl; - this->ChangeState(State_Terminated); - } + /* Change state. */ + { + KScopedSchedulerLock sl; + this->ChangeState(State_Terminated); + } - /* Close. */ - this->Close(); + /* Close. */ + this->Close(); + } } void KProcess::Exit() {