Stratosphere: Fix FS permissions for <4.0.0 KIPs

This commit is contained in:
Michael Scire 2018-10-17 16:26:36 -07:00
parent 781f2597e5
commit 5dc31f001e
10 changed files with 183 additions and 15 deletions

View file

@ -34,7 +34,7 @@ ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__SWITCH__ -DSM_ENABLE_SMHAX -DSM_ENABLE_MITM -DSM_MINIMUM_SESSION_LIMIT=8
CFLAGS += $(INCLUDE) -D__SWITCH__ -DSM_ENABLE_SMHAX -DSM_ENABLE_MITM -DSM_ENABLE_INIT_DEFERS -DSM_MINIMUM_SESSION_LIMIT=8
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17

View file

@ -28,6 +28,9 @@ Result ManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_
case Manager_Cmd_UnregisterProcess:
rc = WrapIpcCommandImpl<&ManagerService::unregister_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Manager_Cmd_AtmosphereEndInitDefers:
rc = WrapIpcCommandImpl<&ManagerService::end_init_defers>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
default:
break;
}
@ -47,3 +50,9 @@ std::tuple<Result> ManagerService::register_process(u64 pid, InBuffer<u8> acid_s
std::tuple<Result> ManagerService::unregister_process(u64 pid) {
return {Registration::UnregisterProcess(pid)};
}
std::tuple<Result> ManagerService::end_init_defers() {
Registration::EndInitDefers();
return {0};
}

View file

@ -20,7 +20,10 @@
enum ManagerServiceCmd {
Manager_Cmd_RegisterProcess = 0,
Manager_Cmd_UnregisterProcess = 1
Manager_Cmd_UnregisterProcess = 1,
Manager_Cmd_AtmosphereEndInitDefers = 65000,
};
class ManagerService final : public IServiceObject {
@ -36,4 +39,5 @@ class ManagerService final : public IServiceObject {
/* Actual commands. */
std::tuple<Result> register_process(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci0_sac);
std::tuple<Result> unregister_process(u64 pid);
std::tuple<Result> end_init_defers();
};

View file

@ -26,6 +26,7 @@ static std::array<Registration::Service, REGISTRATION_LIST_MAX_SERVICE> g_servic
static u64 g_initial_process_id_low = 0;
static u64 g_initial_process_id_high = 0;
static bool g_determined_initial_process_ids = false;
static bool g_end_init_defers = false;
u64 GetServiceNameLength(u64 service) {
u64 service_name_len = 0;
@ -36,6 +37,38 @@ u64 GetServiceNameLength(u64 service) {
return service_name_len;
}
/* Atmosphere extension utilities. */
void Registration::EndInitDefers() {
g_end_init_defers = true;
}
constexpr u64 EncodeNameConstant(const char *name) {
u64 service = 0;
for (unsigned int i = 0; i < sizeof(service); i++) {
if (name[i] == '\x00') {
break;
}
service |= ((u64)name[i]) << (8 * i);
}
return service;
}
bool Registration::ShouldInitDefer(u64 service) {
/* Only enable if compile-time generated. */
#ifndef SM_ENABLE_INIT_DEFERS
return false;
#endif
if (g_end_init_defers) {
return false;
}
/* This is a mechanism by which certain services will always be deferred until sm:m receives a special command. */
/* This can be extended with more services as needed at a later date. */
constexpr u64 FSP_SRV = EncodeNameConstant("fsp-srv");
return service == FSP_SRV;
}
/* Utilities. */
Registration::Process *Registration::GetProcessForPid(u64 pid) {
auto process_it = std::find_if(g_process_list.begin(), g_process_list.end(), member_equals_fn(&Process::pid, pid));
@ -188,11 +221,13 @@ bool Registration::HasService(u64 service) {
Result Registration::GetServiceHandle(u64 pid, u64 service, Handle *out) {
Registration::Service *target_service = GetService(service);
if (target_service == NULL) {
if (target_service == NULL || ShouldInitDefer(service)) {
/* Note: This defers the result until later. */
return RESULT_DEFER_SESSION;
}
/* */
*out = 0;
Result rc;
if (target_service->mitm_pid == 0 || target_service->mitm_pid == pid) {

View file

@ -46,6 +46,9 @@ class Registration {
};
/* Utilities. */
static void EndInitDefers();
static bool ShouldInitDefer(u64 service);
static Registration::Process *GetProcessForPid(u64 pid);
static Registration::Process *GetFreeProcess();
static Registration::Service *GetService(u64 service);

View file

@ -53,7 +53,7 @@ Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id,
Result UserService::handle_deferred() {
/* If we're deferred, GetService failed. */
return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service);;
return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service);
}