From cf5c6cdad9ec4066d763c3317e98f7027d3172a6 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 24 Jun 2019 17:56:00 -0700 Subject: [PATCH] libstrat: integrate sm API, add HasService/HasMitm. --- Makefile | 2 +- include/stratosphere/mitm.hpp | 2 +- include/stratosphere/mitm/mitm_server.hpp | 26 +- include/stratosphere/mitm/sm_mitm.h | 25 -- include/stratosphere/services.hpp | 1 - .../{services/smm_ams.h => sm.hpp} | 16 +- include/stratosphere/sm/sm_api.hpp | 31 ++ include/stratosphere/sm/sm_manager_api.hpp | 31 ++ include/stratosphere/sm/sm_mitm_api.hpp | 30 ++ include/stratosphere/sm/sm_types.hpp | 71 ++++ include/stratosphere/utilities.hpp | 12 - source/sm/sm_ams.c | 309 ++++++++++++++++++ source/sm/sm_ams.h | 27 ++ source/sm/sm_api.cpp | 52 +++ source/sm/sm_manager_api.cpp | 44 +++ source/sm/sm_mitm_api.cpp | 57 ++++ source/sm/sm_utils.cpp | 38 +++ source/sm/sm_utils.hpp | 53 +++ source/{ => sm}/smm_ams.c | 38 +-- source/sm/smm_ams.h | 19 ++ source/sm_mitm.c | 230 ------------- 21 files changed, 784 insertions(+), 330 deletions(-) delete mode 100644 include/stratosphere/mitm/sm_mitm.h rename include/stratosphere/{services/smm_ams.h => sm.hpp} (74%) create mode 100644 include/stratosphere/sm/sm_api.hpp create mode 100644 include/stratosphere/sm/sm_manager_api.hpp create mode 100644 include/stratosphere/sm/sm_mitm_api.hpp create mode 100644 include/stratosphere/sm/sm_types.hpp create mode 100644 source/sm/sm_ams.c create mode 100644 source/sm/sm_ams.h create mode 100644 source/sm/sm_api.cpp create mode 100644 source/sm/sm_manager_api.cpp create mode 100644 source/sm/sm_mitm_api.cpp create mode 100644 source/sm/sm_utils.cpp create mode 100644 source/sm/sm_utils.hpp rename source/{ => sm}/smm_ams.c (62%) create mode 100644 source/sm/smm_ams.h delete mode 100644 source/sm_mitm.c diff --git a/Makefile b/Makefile index 8f2c2e97..c8f2e846 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ include $(DEVKITPRO)/libnx/switch_rules # INCLUDES is a list of directories containing header files #--------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR)) -SOURCES := source source/spl source/spl/smc source/updater source/patcher source/map source/rnd source/util +SOURCES := source source/spl source/spl/smc source/updater source/patcher source/map source/rnd source/util source/sm DATA := data INCLUDES := include diff --git a/include/stratosphere/mitm.hpp b/include/stratosphere/mitm.hpp index 1f7a4c32..bdfa8562 100644 --- a/include/stratosphere/mitm.hpp +++ b/include/stratosphere/mitm.hpp @@ -16,7 +16,7 @@ #pragma once -#include "mitm/sm_mitm.h" +#include "sm.hpp" #include "ipc.hpp" diff --git a/include/stratosphere/mitm/mitm_server.hpp b/include/stratosphere/mitm/mitm_server.hpp index 5fd688fb..20edceb7 100644 --- a/include/stratosphere/mitm/mitm_server.hpp +++ b/include/stratosphere/mitm/mitm_server.hpp @@ -18,7 +18,6 @@ #include #include "mitm_query_service.hpp" -#include "sm_mitm.h" #include "mitm_session.hpp" #include "../utilities.hpp" @@ -30,29 +29,19 @@ class MitmServer : public IWaitable { private: Handle port_handle; unsigned int max_sessions; - char mitm_name[9]; + sts::sm::ServiceName mitm_name; public: - MitmServer(const char *service_name, unsigned int max_s) : port_handle(0), max_sessions(max_s) { - Handle query_h = 0; - - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstringop-truncation" - DoWithSmMitmSession([&]() { - strncpy(mitm_name, service_name, 8); - mitm_name[8] = '\x00'; - R_ASSERT(smMitMInstall(&this->port_handle, &query_h, mitm_name)); - }); - #pragma GCC diagnostic pop + MitmServer(const char *service_name, unsigned int max_s) : port_handle(0), max_sessions(max_s), mitm_name(sts::sm::ServiceName::Encode(service_name)) { + Handle query_h = INVALID_HANDLE; + R_ASSERT(sts::sm::mitm::InstallMitm(&this->port_handle, &query_h, this->mitm_name)); RegisterMitmServerQueryHandle(query_h, std::move(ServiceObjectHolder(std::move(std::make_shared>())))); } virtual ~MitmServer() override { if (this->port_handle) { - DoWithSmMitmSession([&]() { - R_ASSERT(smMitMUninstall(this->mitm_name)); - }); + R_ASSERT(sts::sm::mitm::UninstallMitm(this->mitm_name)); svcCloseHandle(port_handle); } } @@ -79,10 +68,7 @@ class MitmServer : public IWaitable { }); u64 client_pid; - - DoWithSmMitmSession([&]() { - R_ASSERT(smMitMAcknowledgeSession(forward_service.get(), &client_pid, mitm_name)); - }); + R_ASSERT(sts::sm::mitm::AcknowledgeSession(forward_service.get(), &client_pid, this->mitm_name)); this->GetSessionManager()->AddWaitable(new MitmSession(session_h, client_pid, forward_service, MakeShared(forward_service, client_pid))); return ResultSuccess; diff --git a/include/stratosphere/mitm/sm_mitm.h b/include/stratosphere/mitm/sm_mitm.h deleted file mode 100644 index c2c40c11..00000000 --- a/include/stratosphere/mitm/sm_mitm.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @file sm_mitm.h - * @brief Service manager (sm) IPC wrapper for Atmosphere extensions. - * @author SciresM - * @copyright libnx Authors - */ -#pragma once -#include - -#ifdef __cplusplus -extern "C" { -#endif - -Result smMitMInitialize(void); -void smMitMExit(void); -Result smMitMGetService(Service* service_out, const char *name); -Result smMitMInstall(Handle *handle_out, Handle *query_out, const char *name); -Result smMitMUninstall(const char *name); -Result smMitMAcknowledgeSession(Service *srv_out, u64 *pid_out, const char *name); - -Result smMitMIsRegistered(const char *name); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/include/stratosphere/services.hpp b/include/stratosphere/services.hpp index 4143c0c2..fdd292ab 100644 --- a/include/stratosphere/services.hpp +++ b/include/stratosphere/services.hpp @@ -18,5 +18,4 @@ #include "ipc.hpp" -#include "services/smm_ams.h" #include "services/dmntcht.h" \ No newline at end of file diff --git a/include/stratosphere/services/smm_ams.h b/include/stratosphere/sm.hpp similarity index 74% rename from include/stratosphere/services/smm_ams.h rename to include/stratosphere/sm.hpp index fd857fb1..a334419a 100644 --- a/include/stratosphere/services/smm_ams.h +++ b/include/stratosphere/sm.hpp @@ -17,16 +17,6 @@ #pragma once #include -#ifdef __cplusplus -extern "C" { -#endif - -Result smManagerAmsInitialize(void); -void smManagerAmsExit(void); - -Result smManagerAmsEndInitialDefers(void); -Result smManagerAmsHasMitm(bool *out, const char* name); - -#ifdef __cplusplus -} -#endif \ No newline at end of file +#include "sm/sm_types.hpp" +#include "sm/sm_api.hpp" +#include "sm/sm_mitm_api.hpp" diff --git a/include/stratosphere/sm/sm_api.hpp b/include/stratosphere/sm/sm_api.hpp new file mode 100644 index 00000000..152185e9 --- /dev/null +++ b/include/stratosphere/sm/sm_api.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "sm_types.hpp" + +namespace sts::sm { + + /* Ordinary SM API. */ + Result GetService(Service *out, ServiceName name); + Result RegisterService(Handle *out, ServiceName name, size_t max_sessions, bool is_light); + Result UnregisterService(ServiceName name); + + /* Atmosphere extensions. */ + Result HasService(bool *out, ServiceName name); + +} diff --git a/include/stratosphere/sm/sm_manager_api.hpp b/include/stratosphere/sm/sm_manager_api.hpp new file mode 100644 index 00000000..8c66c826 --- /dev/null +++ b/include/stratosphere/sm/sm_manager_api.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "sm_types.hpp" + +namespace sts::sm::manager { + + /* Manager API. */ + Result RegisterProcess(u64 process_id, const void *acid, size_t acid_size, const void *aci, size_t aci_size); + Result UnregisterProcess(u64 process_id); + + /* Atmosphere extensions. */ + Result EndInitialDefers(); + Result HasMitm(bool *out, ServiceName name); + +} diff --git a/include/stratosphere/sm/sm_mitm_api.hpp b/include/stratosphere/sm/sm_mitm_api.hpp new file mode 100644 index 00000000..b378aac7 --- /dev/null +++ b/include/stratosphere/sm/sm_mitm_api.hpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "sm_types.hpp" + +namespace sts::sm::mitm { + + /* Mitm API. */ + Result InstallMitm(Handle *out_port, Handle *out_query, ServiceName name); + Result UninstallMitm(ServiceName name); + Result AssociateProcessIdAndTitleId(u64 process_id, u64 title_id); + Result AcknowledgeSession(Service *out_service, u64 *out_pid, ServiceName name); + Result HasMitm(bool *out, ServiceName name); + +} diff --git a/include/stratosphere/sm/sm_types.hpp b/include/stratosphere/sm/sm_types.hpp new file mode 100644 index 00000000..57b792d8 --- /dev/null +++ b/include/stratosphere/sm/sm_types.hpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include + +namespace sts::sm { + + struct ServiceName { + static constexpr size_t MaxLength = 8; + + char name[MaxLength]; + + static constexpr ServiceName Encode(const char *name, size_t name_size) { + ServiceName out{}; + + for (size_t i = 0; i < MaxLength; i++) { + if (i < name_size) { + out.name[i] = name[i]; + } else { + out.name[i] = 0; + } + } + + return out; + } + + static constexpr ServiceName Encode(const char *name) { + return Encode(name, std::strlen(name)); + } + }; + static constexpr ServiceName InvalidServiceName = ServiceName::Encode(""); + static_assert(alignof(ServiceName) == 1, "ServiceName definition!"); + + inline bool operator==(const ServiceName &lhs, const ServiceName &rhs) { + return std::memcmp(&lhs, &rhs, sizeof(ServiceName)) == 0; + } + + inline bool operator!=(const ServiceName &lhs, const ServiceName &rhs) { + return !(lhs == rhs); + } + + /* For Debug Monitor extensions. */ + struct ServiceRecord { + ServiceName service; + u64 owner_pid; + u64 max_sessions; + u64 mitm_pid; + u64 mitm_waiting_ack_pid; + bool is_light; + bool mitm_waiting_ack; + }; + static_assert(sizeof(ServiceRecord) == 0x30, "ServiceRecord definition!"); + + /* For process validation. */ + static constexpr u64 InvalidProcessId = static_cast(-1ull); + +} diff --git a/include/stratosphere/utilities.hpp b/include/stratosphere/utilities.hpp index 1df2ed82..a9f993f7 100644 --- a/include/stratosphere/utilities.hpp +++ b/include/stratosphere/utilities.hpp @@ -19,7 +19,6 @@ #include #include "hossynch.hpp" -#include "mitm/sm_mitm.h" static inline uintptr_t GetIoMapping(const u64 io_addr, const u64 io_size) { u64 vaddr; @@ -117,7 +116,6 @@ static inline bool ShouldBlankProdInfo() { } HosRecursiveMutex &GetSmSessionMutex(); -HosRecursiveMutex &GetSmMitmSessionMutex(); template static void DoWithSmSession(F f) { @@ -128,13 +126,3 @@ static void DoWithSmSession(F f) { smExit(); } } - -template -static void DoWithSmMitmSession(F f) { - std::scoped_lock lk(GetSmMitmSessionMutex()); - { - R_ASSERT(smMitMInitialize()); - f(); - smMitMExit(); - } -} diff --git a/source/sm/sm_ams.c b/source/sm/sm_ams.c new file mode 100644 index 00000000..2b1ea46f --- /dev/null +++ b/source/sm/sm_ams.c @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include "sm_ams.h" + +static Service g_smMitmSrv; +static u64 g_mitmRefCnt; + +Result smAtmosphereHasService(bool *out, const char *name) { + IpcCommand c; + ipcInitialize(&c); + Service *srv = smGetServiceSession(); + + struct { + u64 magic; + u64 cmd_id; + u64 service_name; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65100; + raw->service_name = smEncodeName(name); + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u8 has_service; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + *out = resp->has_service != 0; + } + } + + return rc; +} + +Result smAtmosphereHasMitm(bool *out, const char *name) { + IpcCommand c; + ipcInitialize(&c); + Service *srv = smGetServiceSession(); + + struct { + u64 magic; + u64 cmd_id; + u64 service_name; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65004; + raw->service_name = smEncodeName(name); + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u8 has_mitm; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + *out = resp->has_mitm != 0; + } + } + + return rc; +} + +Result smAtmosphereMitmInitialize(void) { + atomicIncrement64(&g_mitmRefCnt); + + if (serviceIsActive(&g_smMitmSrv)) + return 0; + + Handle sm_handle; + Result rc = svcConnectToNamedPort(&sm_handle, "sm:"); + while (R_VALUE(rc) == KERNELRESULT(NotFound)) { + svcSleepThread(50000000ul); + rc = svcConnectToNamedPort(&sm_handle, "sm:"); + } + + if (R_SUCCEEDED(rc)) { + serviceCreate(&g_smMitmSrv, sm_handle); + } + + if (R_SUCCEEDED(rc)) { + IpcCommand c; + ipcInitialize(&c); + ipcSendPid(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 zero; + u64 reserved[2]; + } *raw; + + raw = serviceIpcPrepareHeader(&g_smMitmSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 0; + raw->zero = 0; + + rc = serviceIpcDispatch(&g_smMitmSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + + struct { + u64 magic; + u64 result; + } *resp; + serviceIpcParse(&g_smMitmSrv, &r, sizeof(*resp)); + + resp = r.Raw; + rc = resp->result; + } + } + + if (R_FAILED(rc)) + smAtmosphereMitmExit(); + + return rc; +} + +void smAtmosphereMitmExit(void) { + if (atomicDecrement64(&g_mitmRefCnt) == 0) { + serviceClose(&g_smMitmSrv); + } +} + +Result smAtmosphereMitmInstall(Handle *handle_out, Handle *query_out, const char *name) { + IpcCommand c; + ipcInitialize(&c); + Service *srv = &g_smMitmSrv; + + struct { + u64 magic; + u64 cmd_id; + u64 service_name; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65000; + raw->service_name = smEncodeName(name); + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + *handle_out = r.Handles[0]; + *query_out = r.Handles[1]; + } + } + + return rc; +} + +Result smAtmosphereMitmUninstall(const char *name) { + IpcCommand c; + ipcInitialize(&c); + Service *srv = &g_smMitmSrv; + + struct { + u64 magic; + u64 cmd_id; + u64 service_name; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65001; + raw->service_name = smEncodeName(name); + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + rc = resp->result; + } + + return rc; +} + +Result smAtmosphereMitmAssociateProcessIdAndTitleId(u64 pid, u64 tid) { + IpcCommand c; + ipcInitialize(&c); + Service *srv = &g_smMitmSrv; + + struct { + u64 magic; + u64 cmd_id; + u64 pid; + u64 tid; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65002; + raw->pid = pid; + raw->tid = tid; + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result smAtmosphereMitmAcknowledgeSession(Service *srv_out, u64 *pid_out, const char *name) { + IpcCommand c; + ipcInitialize(&c); + Service *srv = &g_smMitmSrv; + + struct { + u64 magic; + u64 cmd_id; + u64 service_name; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = 65003; + raw->service_name = smEncodeName(name); + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u64 pid; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + if (R_SUCCEEDED(rc)) { + *pid_out = resp->pid; + serviceCreate(srv_out, r.Handles[0]); + } + } + + return rc; +} diff --git a/source/sm/sm_ams.h b/source/sm/sm_ams.h new file mode 100644 index 00000000..1b6e60a6 --- /dev/null +++ b/source/sm/sm_ams.h @@ -0,0 +1,27 @@ +/** + * @file sm_ams.h + * @brief Service manager (sm) IPC wrapper for Atmosphere extensions. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +Result smAtmosphereHasService(bool *out, const char *name); +Result smAtmosphereHasMitm(bool *out, const char *name); + +Result smAtmosphereMitmInitialize(void); +void smAtmosphereMitmExit(void); + +Result smAtmosphereMitmInstall(Handle *handle_out, Handle *query_out, const char *name); +Result smAtmosphereMitmUninstall(const char *name); +Result smAtmosphereMitmAssociateProcessIdAndTitleId(u64 pid, u64 tid); +Result smAtmosphereMitmAcknowledgeSession(Service *srv_out, u64 *pid_out, const char *name); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/source/sm/sm_api.cpp b/source/sm/sm_api.cpp new file mode 100644 index 00000000..53108607 --- /dev/null +++ b/source/sm/sm_api.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "sm_ams.h" +#include "sm_utils.hpp" + +namespace sts::sm { + + /* Ordinary SM API. */ + Result GetService(Service *out, ServiceName name) { + return impl::DoWithUserSession([&]() { + return smGetService(out, name.name); + }); + } + + Result RegisterService(Handle *out, ServiceName name, size_t max_sessions, bool is_light) { + return impl::DoWithUserSession([&]() { + return smRegisterService(out, name.name, is_light, static_cast(max_sessions)); + }); + } + + Result UnregisterService(ServiceName name) { + return impl::DoWithUserSession([&]() { + return smUnregisterService(name.name); + }); + } + + /* Atmosphere extensions. */ + Result HasService(bool *out, ServiceName name) { + return impl::DoWithUserSession([&]() { + return smAtmosphereHasService(out, name.name); + }); + } + +} diff --git a/source/sm/sm_manager_api.cpp b/source/sm/sm_manager_api.cpp new file mode 100644 index 00000000..dd4818d4 --- /dev/null +++ b/source/sm/sm_manager_api.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include "smm_ams.h" + +namespace sts::sm::manager { + + /* Manager API. */ + Result RegisterProcess(u64 process_id, const void *acid, size_t acid_size, const void *aci, size_t aci_size) { + return smManagerRegisterProcess(process_id, acid, acid_size, aci, aci_size); + } + + Result UnregisterProcess(u64 process_id) { + return smManagerUnregisterProcess(process_id); + } + + /* Atmosphere extensions. */ + Result EndInitialDefers() { + return smManagerAtmosphereEndInitialDefers(); + } + + Result HasMitm(bool *out, ServiceName name) { + return smManagerAtmosphereHasMitm(out, name.name); + } + +} diff --git a/source/sm/sm_mitm_api.cpp b/source/sm/sm_mitm_api.cpp new file mode 100644 index 00000000..640ca54b --- /dev/null +++ b/source/sm/sm_mitm_api.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include "sm_ams.h" +#include "sm_utils.hpp" + +namespace sts::sm::mitm { + + /* Mitm API. */ + Result InstallMitm(Handle *out_port, Handle *out_query, ServiceName name) { + return impl::DoWithMitmSession([&]() { + return smAtmosphereMitmInstall(out_port, out_query, name.name); + }); + } + + Result UninstallMitm(ServiceName name) { + return impl::DoWithMitmSession([&]() { + return smAtmosphereMitmUninstall(name.name); + }); + } + + Result AssociateProcessIdAndTitleId(u64 process_id, u64 title_id) { + return impl::DoWithMitmSession([&]() { + return smAtmosphereMitmAssociateProcessIdAndTitleId(process_id, title_id); + }); + } + + Result AcknowledgeSession(Service *out_service, u64 *out_pid, ServiceName name) { + return impl::DoWithMitmSession([&]() { + return smAtmosphereMitmAcknowledgeSession(out_service, out_pid, name.name); + }); + } + + Result HasMitm(bool *out, ServiceName name) { + return impl::DoWithUserSession([&]() { + return smAtmosphereHasMitm(out, name.name); + }); + } + +} diff --git a/source/sm/sm_utils.cpp b/source/sm/sm_utils.cpp new file mode 100644 index 00000000..c2cd1c25 --- /dev/null +++ b/source/sm/sm_utils.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "sm_utils.hpp" + +namespace sts::sm::impl { + + namespace { + + /* Globals. */ + HosRecursiveMutex g_user_session_mutex; + HosRecursiveMutex g_mitm_session_mutex; + + } + + /* Utilities. */ + HosRecursiveMutex &GetUserSessionMutex() { + return g_user_session_mutex; + } + + HosRecursiveMutex &GetMitmSessionMutex() { + return g_mitm_session_mutex; + } + +} diff --git a/source/sm/sm_utils.hpp b/source/sm/sm_utils.hpp new file mode 100644 index 00000000..410806f0 --- /dev/null +++ b/source/sm/sm_utils.hpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include + +#include "sm_ams.h" + +namespace sts::sm::impl { + + /* Utilities. */ + HosRecursiveMutex &GetUserSessionMutex(); + HosRecursiveMutex &GetMitmSessionMutex(); + + template + Result DoWithUserSession(F f) { + std::scoped_lock lk(GetUserSessionMutex()); + { + R_ASSERT(smInitialize()); + ON_SCOPE_EXIT { smExit(); }; + + return f(); + } + } + + template + Result DoWithMitmSession(F f) { + std::scoped_lock lk(GetMitmSessionMutex()); + { + R_ASSERT(smAtmosphereMitmInitialize()); + ON_SCOPE_EXIT { smAtmosphereMitmExit(); }; + + return f(); + } + } + +} diff --git a/source/smm_ams.c b/source/sm/smm_ams.c similarity index 62% rename from source/smm_ams.c rename to source/sm/smm_ams.c index 3820cfd7..6e7a90da 100644 --- a/source/smm_ams.c +++ b/source/sm/smm_ams.c @@ -15,41 +15,24 @@ */ #include -#include -#include +#include "smm_ams.h" -static Service g_smManagerAmsSrv; -static u64 g_smManagerAmsRefcnt; - -Result smManagerAmsInitialize(void) { - atomicIncrement64(&g_smManagerAmsRefcnt); - - if (serviceIsActive(&g_smManagerAmsSrv)) - return 0; - - return smGetService(&g_smManagerAmsSrv, "sm:m"); -} - -void smManagerAmsExit(void) { - if (atomicDecrement64(&g_smManagerAmsRefcnt) == 0) - serviceClose(&g_smManagerAmsSrv); -} - -Result smManagerAmsEndInitialDefers(void) { +Result smManagerAtmosphereEndInitialDefers(void) { IpcCommand c; ipcInitialize(&c); + Service *srv = smManagerGetServiceSession(); struct { u64 magic; u64 cmd_id; } *raw; - raw = serviceIpcPrepareHeader(&g_smManagerAmsSrv, &c, sizeof(*raw)); + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 65000; - Result rc = serviceIpcDispatch(&g_smManagerAmsSrv); + Result rc = serviceIpcDispatch(srv); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -58,7 +41,7 @@ Result smManagerAmsEndInitialDefers(void) { u64 result; } *resp; - serviceIpcParse(&g_smManagerAmsSrv, &r, sizeof(*resp)); + serviceIpcParse(srv, &r, sizeof(*resp)); resp = r.Raw; rc = resp->result; @@ -68,9 +51,10 @@ Result smManagerAmsEndInitialDefers(void) { } -Result smManagerAmsHasMitm(bool *out, const char* name) { +Result smManagerAtmosphereHasMitm(bool *out, const char* name) { IpcCommand c; ipcInitialize(&c); + Service *srv = smManagerGetServiceSession(); struct { u64 magic; @@ -78,12 +62,12 @@ Result smManagerAmsHasMitm(bool *out, const char* name) { u64 service_name; } *raw; - raw = serviceIpcPrepareHeader(&g_smManagerAmsSrv, &c, sizeof(*raw)); + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 65001; raw->service_name = smEncodeName(name); - Result rc = serviceIpcDispatch(&g_smManagerAmsSrv); + Result rc = serviceIpcDispatch(srv); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -93,7 +77,7 @@ Result smManagerAmsHasMitm(bool *out, const char* name) { u8 has_mitm; } *resp; - serviceIpcParse(&g_smManagerAmsSrv, &r, sizeof(*resp)); + serviceIpcParse(srv, &r, sizeof(*resp)); resp = r.Raw; rc = resp->result; diff --git a/source/sm/smm_ams.h b/source/sm/smm_ams.h new file mode 100644 index 00000000..2e6e0acd --- /dev/null +++ b/source/sm/smm_ams.h @@ -0,0 +1,19 @@ +/** + * @file smm_ams.h + * @brief Service manager manager (sm:m) IPC wrapper for Atmosphere extensions. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +Result smManagerAtmosphereEndInitialDefers(void); +Result smManagerAtmosphereHasMitm(bool *out, const char* name); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/source/sm_mitm.c b/source/sm_mitm.c deleted file mode 100644 index 61686fdf..00000000 --- a/source/sm_mitm.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2018-2019 Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include - -static Handle g_smMitmHandle = INVALID_HANDLE; -static u64 g_refCnt; - -Result smMitMInitialize(void) { - atomicIncrement64(&g_refCnt); - - if (g_smMitmHandle != INVALID_HANDLE) - return 0; - - Result rc = svcConnectToNamedPort(&g_smMitmHandle, "sm:"); - - if (R_SUCCEEDED(rc)) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 zero; - u64 reserved[2]; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->zero = 0; - - rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - } - - if (R_FAILED(rc)) - smExit(); - - return rc; -} - -void smMitMExit(void) { - if (atomicDecrement64(&g_refCnt) == 0) { - svcCloseHandle(g_smMitmHandle); - g_smMitmHandle = INVALID_HANDLE; - } -} - -Result smMitMGetService(Service* service_out, const char *name_str) -{ - u64 name = smEncodeName(name_str); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 service_name; - u64 reserved[2]; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->service_name = name; - - Result rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - service_out->type = ServiceType_Normal; - service_out->handle = r.Handles[0]; - } - } - - return rc; -} - - -Result smMitMInstall(Handle *handle_out, Handle *query_out, const char *name) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 service_name; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 65000; - raw->service_name = smEncodeName(name); - - Result rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *handle_out = r.Handles[0]; - *query_out = r.Handles[1]; - } - } - - return rc; -} - -Result smMitMUninstall(const char *name) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 service_name; - u64 reserved; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 65001; - raw->service_name = smEncodeName(name); - - Result rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; -} - -Result smMitMAcknowledgeSession(Service *srv_out, u64 *pid_out, const char *name) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 service_name; - u64 reserved; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 65003; - raw->service_name = smEncodeName(name); - - Result rc = ipcDispatch(g_smMitmHandle); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 pid; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - *pid_out = resp->pid; - serviceCreate(srv_out, r.Handles[0]); - } - } - - return rc; - -} \ No newline at end of file