diff --git a/stratosphere/sm/Makefile b/stratosphere/sm/Makefile index 74ee33781..091a82e19 100644 --- a/stratosphere/sm/Makefile +++ b/stratosphere/sm/Makefile @@ -46,7 +46,7 @@ ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE CFLAGS := -g -Wall -O2 -ffunction-sections \ $(ARCH) $(DEFINES) -CFLAGS += $(INCLUDE) -D__SWITCH__ +CFLAGS += $(INCLUDE) -D__SWITCH__ -DSM_ENABLE_SMHAX CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 diff --git a/stratosphere/sm/source/sm_registration.cpp b/stratosphere/sm/source/sm_registration.cpp index a6483cbe9..08ebe5dfc 100644 --- a/stratosphere/sm/source/sm_registration.cpp +++ b/stratosphere/sm/source/sm_registration.cpp @@ -6,6 +6,10 @@ static Registration::Process g_process_list[REGISTRATION_LIST_MAX_PROCESS] = {0}; static Registration::Service g_service_list[REGISTRATION_LIST_MAX_SERVICE] = {0}; +static u64 g_initial_process_id_low = 0; +static u64 g_initial_process_id_high = 0; +static bool g_determined_initial_process_ids = false; + u64 GetServiceNameLength(u64 service) { u64 service_name_len = 0; while (service & 0xFF) { @@ -107,6 +111,30 @@ bool Registration::ValidateSacAgainstRestriction(u8 *r_sac, size_t r_sac_size, u return true; } +void Registration::CacheInitialProcessIdLimits() { + if (g_determined_initial_process_ids) { + return; + } + if (kernelAbove400()) { + svcGetSystemInfo(&g_initial_process_id_low, 2, 0, 0); + svcGetSystemInfo(&g_initial_process_id_high, 2, 0, 0); + } else { + g_initial_process_id_low = 0; + g_initial_process_id_high = REGISTRATION_INITIAL_PID_MAX; + } + g_determined_initial_process_ids = true; +} + +bool Registration::IsInitialProcess(u64 pid) { + CacheInitialProcessIdLimits(); + return g_initial_process_id_low <= pid && pid <= g_initial_process_id_high; +} + +u64 Registration::GetInitialProcessId() { + CacheInitialProcessIdLimits(); + return g_initial_process_id_low; +} + /* Process management. */ Result Registration::RegisterProcess(u64 pid, u8 *acid_sac, size_t acid_sac_size, u8 *aci0_sac, size_t aci0_sac_size) { Registration::Process *proc = GetFreeProcess(); @@ -178,7 +206,7 @@ Result Registration::GetServiceForPid(u64 pid, u64 service, Handle *out) { return 0xC15; } - if (pid >= REGISTRATION_PID_BUILTIN_MAX && service != smEncodeName("dbg:m")) { + if (!IsInitialProcess(pid)) { Registration::Process *proc = GetProcessForPid(pid); if (proc == NULL) { return 0x415; @@ -204,7 +232,7 @@ Result Registration::RegisterServiceForPid(u64 pid, u64 service, u64 max_session return 0xC15; } - if (pid >= REGISTRATION_PID_BUILTIN_MAX) { + if (!IsInitialProcess(pid)) { Registration::Process *proc = GetProcessForPid(pid); if (proc == NULL) { return 0x415; @@ -288,7 +316,7 @@ Result Registration::UnregisterServiceForPid(u64 pid, u64 service) { return 0xE15; } - if (target_service->owner_pid != pid) { + if (!IsInitialProcess(pid) && target_service->owner_pid != pid) { return 0x1015; } diff --git a/stratosphere/sm/source/sm_registration.hpp b/stratosphere/sm/source/sm_registration.hpp index 7ac0f0f89..5c7af1f27 100644 --- a/stratosphere/sm/source/sm_registration.hpp +++ b/stratosphere/sm/source/sm_registration.hpp @@ -4,7 +4,7 @@ #define REGISTRATION_LIST_MAX_PROCESS (0x40) #define REGISTRATION_LIST_MAX_SERVICE (0x100) #define REGISTRATION_MAX_SAC_SIZE (0x200) -#define REGISTRATION_PID_BUILTIN_MAX 0x50 +#define REGISTRATION_INITIAL_PID_MAX 0x50 class Registration { public: @@ -27,6 +27,9 @@ class Registration { static Registration::Service *GetFreeService(); static bool IsValidForSac(u8 *sac, size_t sac_size, u64 service, bool is_host); static bool ValidateSacAgainstRestriction(u8 *r_sac, size_t r_sac_size, u8 *sac, size_t sac_size); + static void CacheInitialProcessIdLimits(); + static bool IsInitialProcess(u64 pid); + static u64 GetInitialProcessId(); /* Process management. */ static Result RegisterProcess(u64 pid, u8 *acid_sac, size_t acid_sac_size, u8 *aci0_sac, size_t aci0_sac_size); diff --git a/stratosphere/sm/source/sm_user_service.cpp b/stratosphere/sm/source/sm_user_service.cpp index f05070c3d..50d2ad055 100644 --- a/stratosphere/sm/source/sm_user_service.cpp +++ b/stratosphere/sm/source/sm_user_service.cpp @@ -39,6 +39,11 @@ std::tuple UserService::initialize(PidDescriptor pid) { std::tuple UserService::get_service(u64 service) { Handle session_h = 0; Result rc = 0x415; +#ifdef SM_ENABLE_SMHAX + if (!this->has_initialized) { + rc = Registration::GetServiceForPid(Registration::GetInitialProcessId(), service, &session_h); + } +#endif if (this->has_initialized) { rc = Registration::GetServiceForPid(this->pid, service, &session_h); } @@ -58,6 +63,11 @@ std::tuple UserService::deferred_get_service(u64 service) { std::tuple UserService::register_service(u64 service, u8 is_light, u32 max_sessions) { Handle service_h = 0; Result rc = 0x415; +#ifdef SM_ENABLE_SMHAX + if (!this->has_initialized) { + rc = Registration::RegisterServiceForPid(Registration::GetInitialProcessId(), service, max_sessions, is_light != 0, &service_h); + } +#endif if (this->has_initialized) { rc = Registration::RegisterServiceForPid(this->pid, service, max_sessions, is_light != 0, &service_h); } @@ -66,6 +76,11 @@ std::tuple UserService::register_service(u64 service, u8 is std::tuple UserService::unregister_service(u64 service) { Result rc = 0x415; +#ifdef SM_ENABLE_SMHAX + if (!this->has_initialized) { + rc = Registration::UnregisterServiceForPid(Registration::GetInitialProcessId(), service); + } +#endif if (this->has_initialized) { rc = Registration::UnregisterServiceForPid(this->pid, service); }