mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-15 23:54:24 -04:00
kern: implement K(Secure)SystemResource
This commit is contained in:
parent
752704a798
commit
2e73f33eb0
20 changed files with 413 additions and 200 deletions
|
@ -117,34 +117,19 @@ namespace ams::kern {
|
|||
this->DeleteThreadLocalRegion(m_plr_address);
|
||||
|
||||
/* Get the used memory size. */
|
||||
const size_t used_memory_size = this->GetUsedUserPhysicalMemorySize();
|
||||
const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize();
|
||||
|
||||
/* Finalize the page table. */
|
||||
m_page_table.Finalize();
|
||||
|
||||
/* Free the system resource. */
|
||||
if (m_system_resource_address != Null<KVirtualAddress>) {
|
||||
/* Check that we have no outstanding allocations. */
|
||||
MESOSPHERE_ABORT_UNLESS(m_memory_block_slab_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_block_info_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_page_table_manager.GetUsed() == 0);
|
||||
/* Finish using our system resource. */
|
||||
{
|
||||
if (m_system_resource->IsSecureResource()) {
|
||||
/* Finalize optimized memory. If memory wasn't optimized, this is a no-op. */
|
||||
Kernel::GetMemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool);
|
||||
}
|
||||
|
||||
/* Free the memory. */
|
||||
KSystemControl::FreeSecureMemory(m_system_resource_address, m_system_resource_num_pages * PageSize, m_memory_pool);
|
||||
|
||||
/* Clear our tracking variables. */
|
||||
m_system_resource_address = Null<KVirtualAddress>;
|
||||
m_system_resource_num_pages = 0;
|
||||
|
||||
/* Finalize optimized memory. If memory wasn't optimized, this is a no-op. */
|
||||
Kernel::GetMemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool);
|
||||
}
|
||||
|
||||
/* Release memory to the resource limit. */
|
||||
if (m_resource_limit != nullptr) {
|
||||
MESOSPHERE_ABORT_UNLESS(used_memory_size >= m_memory_release_hint);
|
||||
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, used_memory_size, used_memory_size - m_memory_release_hint);
|
||||
m_resource_limit->Close();
|
||||
m_system_resource->Close();
|
||||
}
|
||||
|
||||
/* Free all shared memory infos. */
|
||||
|
@ -179,6 +164,13 @@ namespace ams::kern {
|
|||
MESOSPHERE_ABORT_UNLESS(m_partially_used_tlp_tree.empty());
|
||||
MESOSPHERE_ABORT_UNLESS(m_fully_used_tlp_tree.empty());
|
||||
|
||||
/* Release memory to the resource limit. */
|
||||
if (m_resource_limit != nullptr) {
|
||||
MESOSPHERE_ABORT_UNLESS(used_memory_size >= m_memory_release_hint);
|
||||
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, used_memory_size, used_memory_size - m_memory_release_hint);
|
||||
m_resource_limit->Close();
|
||||
}
|
||||
|
||||
/* Log that we finalized for debug. */
|
||||
MESOSPHERE_LOG("KProcess::Finalize() pid=%ld name=%-12s\n", m_process_id, m_name);
|
||||
|
||||
|
@ -267,13 +259,18 @@ namespace ams::kern {
|
|||
MESOSPHERE_ASSERT(res_limit != nullptr);
|
||||
MESOSPHERE_ABORT_UNLESS((params.code_num_pages * PageSize) / PageSize == static_cast<size_t>(params.code_num_pages));
|
||||
|
||||
/* Determine is application. */
|
||||
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication) != 0;
|
||||
|
||||
/* Set members. */
|
||||
m_memory_pool = pool;
|
||||
m_resource_limit = res_limit;
|
||||
m_system_resource_address = Null<KVirtualAddress>;
|
||||
m_system_resource_num_pages = 0;
|
||||
m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource());
|
||||
m_is_immortal = immortal;
|
||||
|
||||
/* Open reference to our system resource. */
|
||||
m_system_resource->Open();
|
||||
|
||||
/* Setup page table. */
|
||||
/* NOTE: Nintendo passes process ID despite not having set it yet. */
|
||||
/* This goes completely unused, but even so... */
|
||||
|
@ -281,11 +278,7 @@ namespace ams::kern {
|
|||
const auto as_type = static_cast<ams::svc::CreateProcessFlag>(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask);
|
||||
const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0;
|
||||
const bool enable_das_merge = (params.flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0;
|
||||
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication) != 0;
|
||||
auto *mem_block_manager = std::addressof(is_app ? Kernel::GetApplicationMemoryBlockManager() : Kernel::GetSystemMemoryBlockManager());
|
||||
auto *block_info_manager = std::addressof(is_app ? Kernel::GetApplicationBlockInfoManager() : Kernel::GetSystemBlockInfoManager());
|
||||
auto *pt_manager = std::addressof(is_app ? Kernel::GetApplicationPageTableManager() : Kernel::GetSystemPageTableManager());
|
||||
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, params.code_num_pages * PageSize, mem_block_manager, block_info_manager, pt_manager, res_limit));
|
||||
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, params.code_num_pages * PageSize, m_system_resource, res_limit));
|
||||
}
|
||||
ON_RESULT_FAILURE { m_page_table.Finalize(); };
|
||||
|
||||
|
@ -328,64 +321,35 @@ namespace ams::kern {
|
|||
const size_t code_size = code_num_pages * PageSize;
|
||||
const size_t system_resource_size = system_resource_num_pages * PageSize;
|
||||
|
||||
/* Reserve memory for the system resource. */
|
||||
KScopedResourceReservation memory_reservation(this, ams::svc::LimitableResource_PhysicalMemoryMax, code_size + KSystemControl::CalculateRequiredSecureMemorySize(system_resource_size, pool));
|
||||
/* Reserve memory for our code resource. */
|
||||
KScopedResourceReservation memory_reservation(this, ams::svc::LimitableResource_PhysicalMemoryMax, code_size);
|
||||
R_UNLESS(memory_reservation.Succeeded(), svc::ResultLimitReached());
|
||||
|
||||
/* Setup page table resource objects. */
|
||||
KMemoryBlockSlabManager *mem_block_manager;
|
||||
KBlockInfoManager *block_info_manager;
|
||||
KPageTableManager *pt_manager;
|
||||
|
||||
m_system_resource_address = Null<KVirtualAddress>;
|
||||
m_system_resource_num_pages = 0;
|
||||
|
||||
/* Setup our system resource. */
|
||||
if (system_resource_num_pages != 0) {
|
||||
/* Allocate secure memory. */
|
||||
R_TRY(KSystemControl::AllocateSecureMemory(std::addressof(m_system_resource_address), system_resource_size, pool));
|
||||
/* Create a secure system resource. */
|
||||
KSecureSystemResource *secure_resource = KSecureSystemResource::Create();
|
||||
R_UNLESS(secure_resource != nullptr, svc::ResultOutOfResource());
|
||||
|
||||
/* Set the number of system resource pages. */
|
||||
MESOSPHERE_ASSERT(m_system_resource_address != Null<KVirtualAddress>);
|
||||
m_system_resource_num_pages = system_resource_num_pages;
|
||||
ON_RESULT_FAILURE { secure_resource->Close(); };
|
||||
|
||||
/* Initialize slab heaps. */
|
||||
const size_t rc_size = util::AlignUp(KPageTableSlabHeap::CalculateReferenceCountSize(system_resource_size), PageSize);
|
||||
m_dynamic_page_manager.Initialize(m_system_resource_address + rc_size, system_resource_size - rc_size);
|
||||
m_page_table_heap.Initialize(std::addressof(m_dynamic_page_manager), 0, GetPointer<KPageTableManager::RefCount>(m_system_resource_address));
|
||||
m_memory_block_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
|
||||
m_block_info_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
|
||||
/* Initialize the secure resource. */
|
||||
R_TRY(secure_resource->Initialize(system_resource_size, m_resource_limit, m_memory_pool));
|
||||
|
||||
/* Initialize managers. */
|
||||
m_page_table_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_page_table_heap));
|
||||
m_memory_block_slab_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_memory_block_heap));
|
||||
m_block_info_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_block_info_heap));
|
||||
/* Set our system resource. */
|
||||
m_system_resource = secure_resource;
|
||||
|
||||
mem_block_manager = std::addressof(m_memory_block_slab_manager);
|
||||
block_info_manager = std::addressof(m_block_info_manager);
|
||||
pt_manager = std::addressof(m_page_table_manager);
|
||||
} else {
|
||||
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication);
|
||||
mem_block_manager = std::addressof(is_app ? Kernel::GetApplicationMemoryBlockManager() : Kernel::GetSystemMemoryBlockManager());
|
||||
block_info_manager = std::addressof(is_app ? Kernel::GetApplicationBlockInfoManager() : Kernel::GetSystemBlockInfoManager());
|
||||
pt_manager = std::addressof(is_app ? Kernel::GetApplicationPageTableManager() : Kernel::GetSystemPageTableManager());
|
||||
/* Use the system-wide system resource. */
|
||||
const bool is_app = (params.flags & ams::svc::CreateProcessFlag_IsApplication);
|
||||
m_system_resource = std::addressof(is_app ? Kernel::GetApplicationSystemResource() : Kernel::GetSystemSystemResource());
|
||||
|
||||
/* Open reference to the system resource. */
|
||||
m_system_resource->Open();
|
||||
}
|
||||
|
||||
/* Ensure we don't leak any secure memory we allocated. */
|
||||
ON_RESULT_FAILURE {
|
||||
if (m_system_resource_address != Null<KVirtualAddress>) {
|
||||
/* Check that we have no outstanding allocations. */
|
||||
MESOSPHERE_ABORT_UNLESS(m_memory_block_slab_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_block_info_manager.GetUsed() == 0);
|
||||
MESOSPHERE_ABORT_UNLESS(m_page_table_manager.GetUsed() == 0);
|
||||
|
||||
/* Free the memory. */
|
||||
KSystemControl::FreeSecureMemory(m_system_resource_address, system_resource_size, pool);
|
||||
|
||||
/* Clear our tracking variables. */
|
||||
m_system_resource_address = Null<KVirtualAddress>;
|
||||
m_system_resource_num_pages = 0;
|
||||
}
|
||||
};
|
||||
/* Ensure we clean up our secure resource, if we fail. */
|
||||
ON_RESULT_FAILURE { m_system_resource->Close(); };
|
||||
|
||||
/* Setup page table. */
|
||||
/* NOTE: Nintendo passes process ID despite not having set it yet. */
|
||||
|
@ -394,7 +358,7 @@ namespace ams::kern {
|
|||
const auto as_type = static_cast<ams::svc::CreateProcessFlag>(params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask);
|
||||
const bool enable_aslr = (params.flags & ams::svc::CreateProcessFlag_EnableAslr) != 0;
|
||||
const bool enable_das_merge = (params.flags & ams::svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge) == 0;
|
||||
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, code_size, mem_block_manager, block_info_manager, pt_manager, res_limit));
|
||||
R_TRY(m_page_table.Initialize(m_process_id, as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, params.code_address, code_size, m_system_resource, res_limit));
|
||||
}
|
||||
ON_RESULT_FAILURE_2 { m_page_table.Finalize(); };
|
||||
|
||||
|
@ -413,7 +377,7 @@ namespace ams::kern {
|
|||
MESOSPHERE_ABORT_UNLESS(m_process_id <= ProcessIdMax);
|
||||
|
||||
/* If we should optimize memory allocations, do so. */
|
||||
if (m_system_resource_address != Null<KVirtualAddress> && (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0) {
|
||||
if (m_system_resource->IsSecureResource() && (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0) {
|
||||
R_TRY(Kernel::GetMemoryManager().InitializeOptimizedMemory(m_process_id, pool));
|
||||
}
|
||||
|
||||
|
@ -461,7 +425,7 @@ namespace ams::kern {
|
|||
if (!m_is_immortal) {
|
||||
/* Release resource limit hint. */
|
||||
if (m_resource_limit != nullptr) {
|
||||
m_memory_release_hint = this->GetUsedUserPhysicalMemorySize();
|
||||
m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize();
|
||||
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, 0, m_memory_release_hint);
|
||||
}
|
||||
|
||||
|
@ -880,7 +844,7 @@ namespace ams::kern {
|
|||
size_t KProcess::GetUsedUserPhysicalMemorySize() const {
|
||||
const size_t norm_size = m_page_table.GetNormalMemorySize();
|
||||
const size_t other_size = m_code_size + m_main_thread_stack_size;
|
||||
const size_t sec_size = KSystemControl::CalculateRequiredSecureMemorySize(m_system_resource_num_pages * PageSize, m_memory_pool);
|
||||
const size_t sec_size = m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->CalculateRequiredSecureMemorySize() : 0;
|
||||
|
||||
return norm_size + other_size + sec_size;
|
||||
}
|
||||
|
@ -909,7 +873,7 @@ namespace ams::kern {
|
|||
/* Get the amount of free and used size. */
|
||||
const size_t free_size = m_resource_limit->GetFreeValue(ams::svc::LimitableResource_PhysicalMemoryMax);
|
||||
const size_t used_size = this->GetUsedUserPhysicalMemorySize();
|
||||
const size_t sec_size = KSystemControl::CalculateRequiredSecureMemorySize(m_system_resource_num_pages * PageSize, m_memory_pool);
|
||||
const size_t sec_size = m_system_resource->IsSecureResource() ? static_cast<KSecureSystemResource *>(m_system_resource)->CalculateRequiredSecureMemorySize() : 0;
|
||||
const size_t max_size = m_max_process_memory;
|
||||
|
||||
if (used_size + free_size > max_size) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue