From 65fd967550a818867e41535abc59f0800bda2728 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 1 Oct 2021 17:37:39 -0700 Subject: [PATCH] pm/cfg: simplify initial process id range logic --- .../source/cfg/cfg_privileged_process.cpp | 58 ++++++------------- stratosphere/pm/source/pm_main.cpp | 28 +++++---- 2 files changed, 30 insertions(+), 56 deletions(-) diff --git a/libraries/libstratosphere/source/cfg/cfg_privileged_process.cpp b/libraries/libstratosphere/source/cfg/cfg_privileged_process.cpp index a517b24f1..1d9817674 100644 --- a/libraries/libstratosphere/source/cfg/cfg_privileged_process.cpp +++ b/libraries/libstratosphere/source/cfg/cfg_privileged_process.cpp @@ -19,66 +19,42 @@ namespace ams::cfg { namespace { - /* Convenience definitions. */ - constexpr os::ProcessId InitialProcessIdMinDeprecated = {0x00}; - constexpr os::ProcessId InitialProcessIdMaxDeprecated = {0x50}; - - /* Privileged process globals. */ constinit os::SdkMutex g_lock; constinit bool g_got_privileged_process_status = false; constinit os::ProcessId g_min_initial_process_id = os::InvalidProcessId, g_max_initial_process_id = os::InvalidProcessId; constinit os::ProcessId g_cur_process_id = os::InvalidProcessId; - /* SD card helpers. */ - void GetPrivilegedProcessIdRange(os::ProcessId *out_min, os::ProcessId *out_max) { - os::ProcessId min = os::InvalidProcessId, max = os::InvalidProcessId; - if (hos::GetVersion() >= hos::Version_5_0_0) { - /* On 5.0.0+, we can get precise limits from svcGetSystemInfo. */ - R_ABORT_UNLESS(svcGetSystemInfo(reinterpret_cast(&min), SystemInfoType_InitialProcessIdRange, INVALID_HANDLE, InitialProcessIdRangeInfo_Minimum)); - R_ABORT_UNLESS(svcGetSystemInfo(reinterpret_cast(&max), SystemInfoType_InitialProcessIdRange, INVALID_HANDLE, InitialProcessIdRangeInfo_Maximum)); - } else if (hos::GetVersion() >= hos::Version_4_0_0) { - /* On 4.0.0-4.1.0, we can get the precise limits from normal svcGetInfo. */ - R_ABORT_UNLESS(svcGetInfo(reinterpret_cast(&min), InfoType_InitialProcessIdRange, INVALID_HANDLE, InitialProcessIdRangeInfo_Minimum)); - R_ABORT_UNLESS(svcGetInfo(reinterpret_cast(&max), InfoType_InitialProcessIdRange, INVALID_HANDLE, InitialProcessIdRangeInfo_Maximum)); - } else { - /* On < 4.0.0, we just use hardcoded extents. */ - min = InitialProcessIdMinDeprecated; - max = InitialProcessIdMaxDeprecated; + ALWAYS_INLINE void EnsurePrivilegedProcessStatusCached() { + if (AMS_LIKELY(g_got_privileged_process_status)) { + return; } - *out_min = min; - *out_max = max; - } + std::scoped_lock lk(g_lock); - void GetPrivilegedProcessStatus() { - GetPrivilegedProcessIdRange(&g_min_initial_process_id, &g_max_initial_process_id); - g_cur_process_id = os::GetCurrentProcessId(); - g_got_privileged_process_status = true; + if (AMS_LIKELY(!g_got_privileged_process_status)) { + R_ABORT_UNLESS(svc::GetSystemInfo(std::addressof(g_min_initial_process_id.value), svc::SystemInfoType_InitialProcessIdRange, svc::InvalidHandle, svc::InitialProcessIdRangeInfo_Minimum)); + R_ABORT_UNLESS(svc::GetSystemInfo(std::addressof(g_max_initial_process_id.value), svc::SystemInfoType_InitialProcessIdRange, svc::InvalidHandle, svc::InitialProcessIdRangeInfo_Maximum)); + g_cur_process_id = os::GetCurrentProcessId(); + + g_got_privileged_process_status = true; + } } } - /* Privileged Process utilities. */ bool IsInitialProcess() { - std::scoped_lock lk(g_lock); + /* Cache initial process range and extents. */ + EnsurePrivilegedProcessStatusCached(); - /* If we've not detected, do detection. */ - if (!g_got_privileged_process_status) { - GetPrivilegedProcessStatus(); - } - - /* Determine if we're privileged, and return. */ + /* Determine if we're Initial. */ return g_min_initial_process_id <= g_cur_process_id && g_cur_process_id <= g_max_initial_process_id; } void GetInitialProcessRange(os::ProcessId *out_min, os::ProcessId *out_max) { - std::scoped_lock lk(g_lock); - - /* If we've not detected, do detection. */ - if (!g_got_privileged_process_status) { - GetPrivilegedProcessStatus(); - } + /* Cache initial process range and extents. */ + EnsurePrivilegedProcessStatusCached(); + /* Set output. */ *out_min = g_min_initial_process_id; *out_max = g_max_initial_process_id; } diff --git a/stratosphere/pm/source/pm_main.cpp b/stratosphere/pm/source/pm_main.cpp index 177dbfeeb..22fc05b19 100644 --- a/stratosphere/pm/source/pm_main.cpp +++ b/stratosphere/pm/source/pm_main.cpp @@ -71,21 +71,15 @@ namespace { /* This uses debugging SVCs to retrieve a process's program id. */ ncm::ProgramId GetProcessProgramId(os::ProcessId process_id) { - /* Check if we should return our program id. */ - /* Doing this here works around a bug fixed in 6.0.0. */ - /* Not doing so will cause svcDebugActiveProcess to deadlock on lower firmwares if called for it's own process. */ - if (process_id == os::GetCurrentProcessId()) { - return os::GetCurrentProgramId(); - } - /* Get a debug handle. */ - os::ManagedHandle debug_handle; - R_ABORT_UNLESS(svcDebugActiveProcess(debug_handle.GetPointer(), static_cast(process_id))); + svc::Handle debug_handle; + R_ABORT_UNLESS(svc::DebugActiveProcess(std::addressof(debug_handle), process_id.value)); + ON_SCOPE_EXIT { R_ABORT_UNLESS(svc::CloseHandle(debug_handle)); }; /* Loop until we get the event that tells us about the process. */ svc::DebugEventInfo d; while (true) { - R_ABORT_UNLESS(svcGetDebugEvent(reinterpret_cast(&d), debug_handle.Get())); + R_ABORT_UNLESS(svc::GetDebugEvent(std::addressof(d), debug_handle)); if (d.type == svc::DebugEvent_CreateProcess) { return ncm::ProgramId{d.info.create_process.program_id}; } @@ -95,11 +89,11 @@ namespace { /* This works around a bug fixed by FS in 4.0.0. */ /* Not doing so will cause KIPs with higher process IDs than 7 to be unable to use filesystem services. */ /* It also registers privileged processes with SM, so that their program ids can be known. */ - void RegisterPrivilegedProcess(os::ProcessId process_id) { - fsprUnregisterProgram(static_cast(process_id)); - fsprRegisterProgram(static_cast(process_id), static_cast(process_id), NcmStorageId_BuiltInSystem, PrivilegedFileAccessHeader, sizeof(PrivilegedFileAccessHeader), PrivilegedFileAccessControl, sizeof(PrivilegedFileAccessControl)); + void RegisterPrivilegedProcess(os::ProcessId process_id, ncm::ProgramId program_id) { + fsprUnregisterProgram(process_id.value); + fsprRegisterProgram(process_id.value, process_id.value, NcmStorageId_BuiltInSystem, PrivilegedFileAccessHeader, sizeof(PrivilegedFileAccessHeader), PrivilegedFileAccessControl, sizeof(PrivilegedFileAccessControl)); sm::manager::UnregisterProcess(process_id); - sm::manager::RegisterProcess(process_id, GetProcessProgramId(process_id), cfg::OverrideStatus{}, PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl), PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl)); + sm::manager::RegisterProcess(process_id, program_id, cfg::OverrideStatus{}, PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl), PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl)); } void RegisterPrivilegedProcesses() { @@ -107,13 +101,17 @@ namespace { os::ProcessId min_priv_process_id = os::InvalidProcessId, max_priv_process_id = os::InvalidProcessId; cfg::GetInitialProcessRange(&min_priv_process_id, &max_priv_process_id); + /* Get current process id/program id. */ + const auto cur_process_id = os::GetCurrentProcessId(); + const auto cur_program_id = os::GetCurrentProgramId(); + /* Get list of processes, register all privileged ones. */ s32 num_pids; os::ProcessId pids[ProcessCountMax]; R_ABORT_UNLESS(svc::GetProcessList(&num_pids, reinterpret_cast(pids), ProcessCountMax)); for (s32 i = 0; i < num_pids; i++) { if (min_priv_process_id <= pids[i] && pids[i] <= max_priv_process_id) { - RegisterPrivilegedProcess(pids[i]); + RegisterPrivilegedProcess(pids[i], pids[i] == cur_process_id ? cur_program_id : GetProcessProgramId(pids[i])); } } }