sf: prevent emitting mitm/defer code unless server in process supports it

This commit is contained in:
Michael Scire 2021-10-11 19:01:27 -07:00
parent d27fe8a229
commit bd1bcdf52b
21 changed files with 230 additions and 107 deletions

View file

@ -40,6 +40,8 @@ namespace ams::scs {
static constexpr size_t PointerBufferSize = 0; static constexpr size_t PointerBufferSize = 0;
static constexpr size_t MaxDomains = 6; static constexpr size_t MaxDomains = 6;
static constexpr size_t MaxDomainObjects = 16; static constexpr size_t MaxDomainObjects = 16;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
}; };
class ServerManager final : public sf::hipc::ServerManager<Port_Count, ServerOptions, MaxSessions> { class ServerManager final : public sf::hipc::ServerManager<Port_Count, ServerOptions, MaxSessions> {

View file

@ -24,6 +24,8 @@ namespace ams::sf::hipc {
static constexpr size_t PointerBufferSize = 0; static constexpr size_t PointerBufferSize = 0;
static constexpr size_t MaxDomains = 0; static constexpr size_t MaxDomains = 0;
static constexpr size_t MaxDomainObjects = 0; static constexpr size_t MaxDomainObjects = 0;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
}; };
static constexpr size_t ServerSessionCountMax = 0x40; static constexpr size_t ServerSessionCountMax = 0x40;
@ -72,6 +74,9 @@ namespace ams::sf::hipc {
R_ABORT_UNLESS(sm::mitm::AcknowledgeSession(out_fsrv->get(), out_client_info, m_service_name)); R_ABORT_UNLESS(sm::mitm::AcknowledgeSession(out_fsrv->get(), out_client_info, m_service_name));
} }
}; };
protected:
static constinit inline bool g_is_any_deferred_supported = false;
static constinit inline bool g_is_any_mitm_supported = false;
private: private:
/* Multiple wait management. */ /* Multiple wait management. */
os::MultiWaitType m_multi_wait; os::MultiWaitType m_multi_wait;
@ -84,6 +89,10 @@ namespace ams::sf::hipc {
os::SdkMutex m_deferred_list_mutex; os::SdkMutex m_deferred_list_mutex;
os::MultiWaitType m_deferred_list; os::MultiWaitType m_deferred_list;
/* Boolean values. */
const bool m_is_defer_supported;
const bool m_is_mitm_supported;
private: private:
virtual void RegisterServerSessionToWait(ServerSession *session) override final; virtual void RegisterServerSessionToWait(ServerSession *session) override final;
void LinkToDeferredList(os::MultiWaitHolderType *holder); void LinkToDeferredList(os::MultiWaitHolderType *holder);
@ -102,6 +111,7 @@ namespace ams::sf::hipc {
server->m_is_mitm_server = is_mitm_server; server->m_is_mitm_server = is_mitm_server;
if (is_mitm_server) { if (is_mitm_server) {
/* Mitm server. */ /* Mitm server. */
AMS_ABORT_UNLESS(this->CanManageMitmServers());
os::SetMultiWaitHolderUserData(server, static_cast<uintptr_t>(UserDataTag::MitmServer)); os::SetMultiWaitHolderUserData(server, static_cast<uintptr_t>(UserDataTag::MitmServer));
} else { } else {
/* Non-mitm server. */ /* Non-mitm server. */
@ -148,6 +158,26 @@ namespace ams::sf::hipc {
return ResultSuccess(); return ResultSuccess();
} }
Result InstallMitmServerImpl(os::NativeHandle *out_port_handle, sm::ServiceName service_name, MitmQueryFunction query_func);
protected:
virtual Server *AllocateServer() = 0;
virtual void DestroyServer(Server *server) = 0;
virtual Result OnNeedsToAccept(int port_index, Server *server) {
AMS_UNUSED(port_index, server);
AMS_ABORT("OnNeedsToAccept must be overridden when using indexed ports");
}
template<typename Interface>
Result AcceptImpl(Server *server, SharedPointer<Interface> p) {
return ServerSessionManager::AcceptSession(server->m_port_handle, std::move(p));
}
template<typename Interface>
Result AcceptMitmImpl(Server *server, SharedPointer<Interface> p, std::shared_ptr<::Service> forward_service) {
AMS_ABORT_UNLESS(this->CanManageMitmServers());
return ServerSessionManager::AcceptMitmSession(server->m_port_handle, std::move(p), std::move(forward_service));
}
template<typename Interface> template<typename Interface>
Result RegisterMitmServerImpl(int index, cmif::ServiceObjectHolder &&static_holder, sm::ServiceName service_name) { Result RegisterMitmServerImpl(int index, cmif::ServiceObjectHolder &&static_holder, sm::ServiceName service_name) {
/* Install mitm service. */ /* Install mitm service. */
@ -170,30 +200,11 @@ namespace ams::sf::hipc {
return ResultSuccess(); return ResultSuccess();
} }
Result InstallMitmServerImpl(os::NativeHandle *out_port_handle, sm::ServiceName service_name, MitmQueryFunction query_func);
protected:
virtual Server *AllocateServer() = 0;
virtual void DestroyServer(Server *server) = 0;
virtual Result OnNeedsToAccept(int port_index, Server *server) {
AMS_UNUSED(port_index, server);
AMS_ABORT("OnNeedsToAccept must be overridden when using indexed ports");
}
template<typename Interface>
Result AcceptImpl(Server *server, SharedPointer<Interface> p) {
return ServerSessionManager::AcceptSession(server->m_port_handle, std::move(p));
}
template<typename Interface>
Result AcceptMitmImpl(Server *server, SharedPointer<Interface> p, std::shared_ptr<::Service> forward_service) {
return ServerSessionManager::AcceptMitmSession(server->m_port_handle, std::move(p), std::move(forward_service));
}
public: public:
ServerManagerBase(DomainEntryStorage *entry_storage, size_t entry_count) : ServerManagerBase(DomainEntryStorage *entry_storage, size_t entry_count, bool defer_supported, bool mitm_supported) :
ServerDomainSessionManager(entry_storage, entry_count), ServerDomainSessionManager(entry_storage, entry_count),
m_request_stop_event(os::EventClearMode_ManualClear), m_notify_event(os::EventClearMode_ManualClear), m_request_stop_event(os::EventClearMode_ManualClear), m_notify_event(os::EventClearMode_ManualClear),
m_selection_mutex(), m_deferred_list_mutex() m_selection_mutex(), m_deferred_list_mutex(), m_is_defer_supported(defer_supported), m_is_mitm_supported(mitm_supported)
{ {
/* Link multi-wait holders. */ /* Link multi-wait holders. */
os::InitializeMultiWait(std::addressof(m_multi_wait)); os::InitializeMultiWait(std::addressof(m_multi_wait));
@ -205,6 +216,22 @@ namespace ams::sf::hipc {
os::InitializeMultiWait(std::addressof(m_deferred_list)); os::InitializeMultiWait(std::addressof(m_deferred_list));
} }
static ALWAYS_INLINE bool CanAnyDeferInvokeRequest() {
return g_is_any_deferred_supported;
}
static ALWAYS_INLINE bool CanAnyManageMitmServers() {
return g_is_any_mitm_supported;
}
ALWAYS_INLINE bool CanDeferInvokeRequest() const {
return CanAnyDeferInvokeRequest() && m_is_defer_supported;
}
ALWAYS_INLINE bool CanManageMitmServers() const {
return CanAnyManageMitmServers() && m_is_mitm_supported;
}
template<typename Interface> template<typename Interface>
void RegisterObjectForServer(SharedPointer<Interface> static_object, os::NativeHandle port_handle) { void RegisterObjectForServer(SharedPointer<Interface> static_object, os::NativeHandle port_handle) {
this->RegisterServerImpl(0, cmif::ServiceObjectHolder(std::move(static_object)), port_handle, false); this->RegisterServerImpl(0, cmif::ServiceObjectHolder(std::move(static_object)), port_handle, false);
@ -223,11 +250,6 @@ namespace ams::sf::hipc {
return this->RegisterServerImpl(port_index, cmif::ServiceObjectHolder(), service_name, max_sessions); return this->RegisterServerImpl(port_index, cmif::ServiceObjectHolder(), service_name, max_sessions);
} }
template<typename Interface>
Result RegisterMitmServer(int port_index, sm::ServiceName service_name) {
return this->template RegisterMitmServerImpl<Interface>(port_index, cmif::ServiceObjectHolder(), service_name);
}
/* Processing. */ /* Processing. */
os::MultiWaitHolderType *WaitSignaled(); os::MultiWaitHolderType *WaitSignaled();
@ -267,7 +289,7 @@ namespace ams::sf::hipc {
util::TypedStorage<ServerSession> m_session_storages[MaxSessions]; util::TypedStorage<ServerSession> m_session_storages[MaxSessions];
bool m_session_allocated[MaxSessions]; bool m_session_allocated[MaxSessions];
u8 m_pointer_buffer_storage[0x10 + (MaxSessions * ManagerOptions::PointerBufferSize)]; u8 m_pointer_buffer_storage[0x10 + (MaxSessions * ManagerOptions::PointerBufferSize)];
u8 m_saved_message_storage[0x10 + (MaxSessions * hipc::TlsMessageBufferSize)]; u8 m_saved_message_storage[0x10 + (MaxSessions * (ManagerOptions::CanDeferInvokeRequest ? hipc::TlsMessageBufferSize : 0))];
uintptr_t m_pointer_buffers_start; uintptr_t m_pointer_buffers_start;
uintptr_t m_saved_messages_start; uintptr_t m_saved_messages_start;
@ -337,12 +359,16 @@ namespace ams::sf::hipc {
os::UnlinkMultiWaitHolder(server); os::UnlinkMultiWaitHolder(server);
os::FinalizeMultiWaitHolder(server); os::FinalizeMultiWaitHolder(server);
if (server->m_service_managed) { if (server->m_service_managed) {
if (server->m_is_mitm_server) { if constexpr (ManagerOptions::CanManageMitmServers) {
R_ABORT_UNLESS(sm::mitm::UninstallMitm(server->m_service_name)); if (server->m_is_mitm_server) {
R_ABORT_UNLESS(sm::mitm::UninstallMitm(server->m_service_name));
} else {
R_ABORT_UNLESS(sm::UnregisterService(server->m_service_name));
}
} else { } else {
R_ABORT_UNLESS(sm::UnregisterService(server->m_service_name)); R_ABORT_UNLESS(sm::UnregisterService(server->m_service_name));
} }
R_ABORT_UNLESS(svc::CloseHandle(server->m_port_handle)); os::CloseNativeHandle(server->m_port_handle);
} }
} }
m_server_allocated[index] = false; m_server_allocated[index] = false;
@ -377,10 +403,14 @@ namespace ams::sf::hipc {
} }
virtual cmif::PointerAndSize GetSessionSavedMessageBuffer(const ServerSession *session) const override final { virtual cmif::PointerAndSize GetSessionSavedMessageBuffer(const ServerSession *session) const override final {
return this->GetObjectBySessionIndex(session, m_saved_messages_start, hipc::TlsMessageBufferSize); if constexpr (ManagerOptions::CanDeferInvokeRequest) {
return this->GetObjectBySessionIndex(session, m_saved_messages_start, hipc::TlsMessageBufferSize);
} else {
return cmif::PointerAndSize();
}
} }
public: public:
ServerManager() : ServerManagerBase(m_domain_entry_storages, ManagerOptions::MaxDomainObjects), m_resource_mutex() { ServerManager() : ServerManagerBase(m_domain_entry_storages, ManagerOptions::MaxDomainObjects, ManagerOptions::CanDeferInvokeRequest, ManagerOptions::CanManageMitmServers), m_resource_mutex() {
/* Clear storages. */ /* Clear storages. */
#define SF_SM_MEMCLEAR(obj) if constexpr (sizeof(obj) > 0) { std::memset(obj, 0, sizeof(obj)); } #define SF_SM_MEMCLEAR(obj) if constexpr (sizeof(obj) > 0) { std::memset(obj, 0, sizeof(obj)); }
SF_SM_MEMCLEAR(m_server_storages); SF_SM_MEMCLEAR(m_server_storages);
@ -395,6 +425,14 @@ namespace ams::sf::hipc {
/* Set resource starts. */ /* Set resource starts. */
m_pointer_buffers_start = util::AlignUp(reinterpret_cast<uintptr_t>(m_pointer_buffer_storage), 0x10); m_pointer_buffers_start = util::AlignUp(reinterpret_cast<uintptr_t>(m_pointer_buffer_storage), 0x10);
m_saved_messages_start = util::AlignUp(reinterpret_cast<uintptr_t>(m_saved_message_storage), 0x10); m_saved_messages_start = util::AlignUp(reinterpret_cast<uintptr_t>(m_saved_message_storage), 0x10);
/* Update globals. */
if constexpr (ManagerOptions::CanDeferInvokeRequest) {
ServerManagerBase::g_is_any_deferred_supported = true;
}
if constexpr (ManagerOptions::CanManageMitmServers) {
ServerManagerBase::g_is_any_mitm_supported = true;
}
} }
~ServerManager() { ~ServerManager() {
@ -416,6 +454,12 @@ namespace ams::sf::hipc {
} }
} }
} }
public:
template<typename Interface, bool Enable = ManagerOptions::CanManageMitmServers, typename = typename std::enable_if<Enable>::type>
Result RegisterMitmServer(int port_index, sm::ServiceName service_name) {
AMS_ABORT_UNLESS(this->CanManageMitmServers());
return this->template RegisterMitmServerImpl<Interface>(port_index, cmif::ServiceObjectHolder(), service_name);
}
}; };
} }

View file

@ -48,29 +48,29 @@ namespace ams::sf::hipc {
cmif::ServiceObjectHolder m_srv_obj_holder; cmif::ServiceObjectHolder m_srv_obj_holder;
cmif::PointerAndSize m_pointer_buffer; cmif::PointerAndSize m_pointer_buffer;
cmif::PointerAndSize m_saved_message; cmif::PointerAndSize m_saved_message;
std::shared_ptr<::Service> m_forward_service; util::TypedStorage<std::shared_ptr<::Service>> m_forward_service;
os::NativeHandle m_session_handle; os::NativeHandle m_session_handle;
bool m_is_closed; bool m_is_closed;
bool m_has_received; bool m_has_received;
const bool m_has_forward_service;
public: public:
ServerSession(os::NativeHandle h, cmif::ServiceObjectHolder &&obj) : m_srv_obj_holder(std::move(obj)), m_session_handle(h) { ServerSession(os::NativeHandle h, cmif::ServiceObjectHolder &&obj) : m_srv_obj_holder(std::move(obj)), m_session_handle(h), m_has_forward_service(false) {
hipc::AttachMultiWaitHolderForReply(this, h); hipc::AttachMultiWaitHolderForReply(this, h);
m_is_closed = false; m_is_closed = false;
m_has_received = false; m_has_received = false;
m_forward_service = nullptr;
AMS_ABORT_UNLESS(!this->IsMitmSession()); AMS_ABORT_UNLESS(!this->IsMitmSession());
} }
ServerSession(os::NativeHandle h, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) : m_srv_obj_holder(std::move(obj)), m_session_handle(h) { ServerSession(os::NativeHandle h, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) : m_srv_obj_holder(std::move(obj)), m_session_handle(h), m_has_forward_service(true) {
hipc::AttachMultiWaitHolderForReply(this, h); hipc::AttachMultiWaitHolderForReply(this, h);
m_is_closed = false; m_is_closed = false;
m_has_received = false; m_has_received = false;
m_forward_service = std::move(fsrv); util::ConstructAt(m_forward_service, std::move(fsrv));
AMS_ABORT_UNLESS(this->IsMitmSession()); AMS_ABORT_UNLESS(util::GetReference(m_forward_service) != nullptr);
} }
bool IsMitmSession() const { ALWAYS_INLINE bool IsMitmSession() const {
return m_forward_service != nullptr; return m_has_forward_service;
} }
Result ForwardRequest(const cmif::ServiceDispatchContext &ctx) const; Result ForwardRequest(const cmif::ServiceDispatchContext &ctx) const;

View file

@ -27,9 +27,11 @@ namespace ams::erpt::srv {
namespace { namespace {
struct ErrorReportServerOptions { struct ErrorReportServerOptions {
static constexpr size_t PointerBufferSize = 0; static constexpr size_t PointerBufferSize = 0;
static constexpr size_t MaxDomains = 64; static constexpr size_t MaxDomains = 64;
static constexpr size_t MaxDomainObjects = 2 * ReportCountMax + 5 + 2; static constexpr size_t MaxDomainObjects = 2 * ReportCountMax + 5 + 2;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
}; };
constexpr inline size_t ErrorReportNumServers = 2; constexpr inline size_t ErrorReportNumServers = 2;

View file

@ -26,9 +26,11 @@ namespace ams::htcfs {
static constexpr inline sm::ServiceName ServiceName = sm::ServiceName::Encode("file_io"); static constexpr inline sm::ServiceName ServiceName = sm::ServiceName::Encode("file_io");
struct ServerOptions { struct ServerOptions {
static constexpr size_t PointerBufferSize = 0x1000; static constexpr size_t PointerBufferSize = 0x1000;
static constexpr size_t MaxDomains = 0x10; static constexpr size_t MaxDomains = 0x10;
static constexpr size_t MaxDomainObjects = 0x100; static constexpr size_t MaxDomainObjects = 0x100;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
}; };
using ServerManager = sf::hipc::ServerManager<NumServers, ServerOptions, MaxSessions>; using ServerManager = sf::hipc::ServerManager<NumServers, ServerOptions, MaxSessions>;

View file

@ -25,9 +25,11 @@ namespace ams::htcs::server {
static constexpr inline sm::ServiceName ServiceName = sm::ServiceName::Encode("htcs"); static constexpr inline sm::ServiceName ServiceName = sm::ServiceName::Encode("htcs");
struct ServerOptions { struct ServerOptions {
static constexpr size_t PointerBufferSize = 0x80; static constexpr size_t PointerBufferSize = 0x80;
static constexpr size_t MaxDomains = 0x10; static constexpr size_t MaxDomains = 0x10;
static constexpr size_t MaxDomainObjects = 100; static constexpr size_t MaxDomainObjects = 100;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
}; };
using ServerManager = sf::hipc::ServerManager<NumServers, ServerOptions, MaxSessions>; using ServerManager = sf::hipc::ServerManager<NumServers, ServerOptions, MaxSessions>;

View file

@ -30,9 +30,11 @@ namespace ams::lm::srv {
constexpr inline size_t PortCountMax = 2; constexpr inline size_t PortCountMax = 2;
struct ServerManagerOptions { struct ServerManagerOptions {
static constexpr size_t PointerBufferSize = 0x400; static constexpr size_t PointerBufferSize = 0x400;
static constexpr size_t MaxDomains = 31; static constexpr size_t MaxDomains = 31;
static constexpr size_t MaxDomainObjects = 61; static constexpr size_t MaxDomainObjects = 61;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
}; };
using ServerManager = sf::hipc::ServerManager<PortCountMax, ServerManagerOptions, SessionCountMax>; using ServerManager = sf::hipc::ServerManager<PortCountMax, ServerManagerOptions, SessionCountMax>;

View file

@ -27,7 +27,7 @@ namespace ams::sf::hipc::impl {
class MitmQueryService { class MitmQueryService {
private: private:
ServerManagerBase::MitmQueryFunction m_query_function; const ServerManagerBase::MitmQueryFunction m_query_function;
public: public:
MitmQueryService(ServerManagerBase::MitmQueryFunction qf) : m_query_function(qf) { /* ... */ } MitmQueryService(ServerManagerBase::MitmQueryFunction qf) : m_query_function(qf) { /* ... */ }

View file

@ -32,7 +32,7 @@ namespace ams::sf::hipc {
private: private:
ServerDomainSessionManager *m_manager; ServerDomainSessionManager *m_manager;
ServerSession *m_session; ServerSession *m_session;
bool m_is_mitm_session; const bool m_is_mitm_session;
private: private:
Result CloneCurrentObjectImpl(sf::OutMoveHandle &out_client_handle, ServerSessionManager *tagged_manager) { Result CloneCurrentObjectImpl(sf::OutMoveHandle &out_client_handle, ServerSessionManager *tagged_manager) {
/* Clone the object. */ /* Clone the object. */
@ -47,9 +47,12 @@ namespace ams::sf::hipc {
if (!m_is_mitm_session) { if (!m_is_mitm_session) {
R_ABORT_UNLESS(tagged_manager->RegisterSession(server_handle, std::move(clone))); R_ABORT_UNLESS(tagged_manager->RegisterSession(server_handle, std::move(clone)));
} else { } else {
/* Check that we can create a mitm session. */
AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers());
/* Clone the forward service. */ /* Clone the forward service. */
std::shared_ptr<::Service> new_forward_service = std::move(ServerSession::CreateForwardService()); std::shared_ptr<::Service> new_forward_service = std::move(ServerSession::CreateForwardService());
R_ABORT_UNLESS(serviceClone(m_session->m_forward_service.get(), new_forward_service.get())); R_ABORT_UNLESS(serviceClone(util::GetReference(m_session->m_forward_service).get(), new_forward_service.get()));
R_ABORT_UNLESS(tagged_manager->RegisterMitmSession(server_handle, std::move(clone), std::move(new_forward_service))); R_ABORT_UNLESS(tagged_manager->RegisterMitmSession(server_handle, std::move(clone), std::move(new_forward_service)));
} }
@ -58,7 +61,7 @@ namespace ams::sf::hipc {
return ResultSuccess(); return ResultSuccess();
} }
public: public:
explicit HipcManagerImpl(ServerDomainSessionManager *m, ServerSession *s) : m_manager(m), m_session(s), m_is_mitm_session(s->m_forward_service != nullptr) { explicit HipcManagerImpl(ServerDomainSessionManager *m, ServerSession *s) : m_manager(m), m_session(s), m_is_mitm_session(s->IsMitmSession()) {
/* ... */ /* ... */
} }
@ -70,15 +73,18 @@ namespace ams::sf::hipc {
/* Set up the new domain object. */ /* Set up the new domain object. */
cmif::DomainObjectId object_id = cmif::InvalidDomainObjectId; cmif::DomainObjectId object_id = cmif::InvalidDomainObjectId;
if (m_is_mitm_session) { if (m_is_mitm_session) {
/* Check that we can create a mitm session. */
AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers());
/* Make a new shared pointer to manage the allocated domain. */ /* Make a new shared pointer to manage the allocated domain. */
SharedPointer<cmif::MitmDomainServiceObject> cmif_domain(static_cast<cmif::MitmDomainServiceObject *>(domain), false); SharedPointer<cmif::MitmDomainServiceObject> cmif_domain(static_cast<cmif::MitmDomainServiceObject *>(domain), false);
/* Convert the remote session to domain. */ /* Convert the remote session to domain. */
AMS_ABORT_UNLESS(m_session->m_forward_service->own_handle); AMS_ABORT_UNLESS(util::GetReference(m_session->m_forward_service)->own_handle);
R_TRY(serviceConvertToDomain(m_session->m_forward_service.get())); R_TRY(serviceConvertToDomain(util::GetReference(m_session->m_forward_service).get()));
/* The object ID reservation cannot fail here, as that would cause desynchronization from target domain. */ /* The object ID reservation cannot fail here, as that would cause desynchronization from target domain. */
object_id = cmif::DomainObjectId{m_session->m_forward_service->object_id}; object_id = cmif::DomainObjectId{util::GetReference(m_session->m_forward_service)->object_id};
domain->ReserveSpecificIds(std::addressof(object_id), 1); domain->ReserveSpecificIds(std::addressof(object_id), 1);
/* Register the object. */ /* Register the object. */
@ -116,14 +122,17 @@ namespace ams::sf::hipc {
if (!object) { if (!object) {
R_UNLESS(m_is_mitm_session, sf::hipc::ResultDomainObjectNotFound()); R_UNLESS(m_is_mitm_session, sf::hipc::ResultDomainObjectNotFound());
/* Check that we can create a mitm session. */
AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers());
os::NativeHandle handle; os::NativeHandle handle;
R_TRY(cmifCopyFromCurrentDomain(m_session->m_forward_service->session, object_id.value, std::addressof(handle))); R_TRY(cmifCopyFromCurrentDomain(util::GetReference(m_session->m_forward_service)->session, object_id.value, std::addressof(handle)));
out.SetValue(handle, false); out.SetValue(handle, false);
return ResultSuccess(); return ResultSuccess();
} }
if (!m_is_mitm_session || object_id.value != serviceGetObjectId(m_session->m_forward_service.get())) { if (!m_is_mitm_session || (ServerManagerBase::CanAnyManageMitmServers() && object_id.value != serviceGetObjectId(util::GetReference(m_session->m_forward_service).get()))) {
/* Create new session handles. */ /* Create new session handles. */
os::NativeHandle server_handle, client_handle; os::NativeHandle server_handle, client_handle;
R_ABORT_UNLESS(hipc::CreateSession(std::addressof(server_handle), std::addressof(client_handle))); R_ABORT_UNLESS(hipc::CreateSession(std::addressof(server_handle), std::addressof(client_handle)));
@ -134,9 +143,12 @@ namespace ams::sf::hipc {
/* Set output client handle. */ /* Set output client handle. */
out.SetValue(client_handle, false); out.SetValue(client_handle, false);
} else { } else {
/* Check that we can create a mitm session. */
AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers());
/* Copy from the target domain. */ /* Copy from the target domain. */
os::NativeHandle new_forward_target; os::NativeHandle new_forward_target;
R_TRY(cmifCopyFromCurrentDomain(m_session->m_forward_service->session, object_id.value, std::addressof(new_forward_target))); R_TRY(cmifCopyFromCurrentDomain(util::GetReference(m_session->m_forward_service)->session, object_id.value, std::addressof(new_forward_target)));
/* Create new session handles. */ /* Create new session handles. */
os::NativeHandle server_handle, client_handle; os::NativeHandle server_handle, client_handle;

View file

@ -114,21 +114,34 @@ namespace ams::sf::hipc {
ServerSession *session = static_cast<ServerSession *>(holder); ServerSession *session = static_cast<ServerSession *>(holder);
cmif::PointerAndSize tls_message(svc::GetThreadLocalRegion()->message_buffer, hipc::TlsMessageBufferSize); cmif::PointerAndSize tls_message(svc::GetThreadLocalRegion()->message_buffer, hipc::TlsMessageBufferSize);
const cmif::PointerAndSize &saved_message = session->m_saved_message; if (this->CanDeferInvokeRequest()) {
AMS_ABORT_UNLESS(tls_message.GetSize() == saved_message.GetSize()); const cmif::PointerAndSize &saved_message = session->m_saved_message;
if (!session->m_has_received) { AMS_ABORT_UNLESS(tls_message.GetSize() == saved_message.GetSize());
R_TRY(this->ReceiveRequest(session, tls_message));
session->m_has_received = true;
std::memcpy(saved_message.GetPointer(), tls_message.GetPointer(), tls_message.GetSize());
} else {
/* We were deferred and are re-receiving, so just memcpy. */
std::memcpy(tls_message.GetPointer(), saved_message.GetPointer(), tls_message.GetSize());
}
/* Treat a meta "Context Invalidated" message as a success. */ if (!session->m_has_received) {
R_TRY_CATCH(this->ProcessRequest(session, tls_message)) { R_TRY(this->ReceiveRequest(session, tls_message));
R_CONVERT(sf::impl::ResultRequestInvalidated, ResultSuccess()); session->m_has_received = true;
} R_END_TRY_CATCH; std::memcpy(saved_message.GetPointer(), tls_message.GetPointer(), tls_message.GetSize());
} else {
/* We were deferred and are re-receiving, so just memcpy. */
std::memcpy(tls_message.GetPointer(), saved_message.GetPointer(), tls_message.GetSize());
}
/* Treat a meta "Context Invalidated" message as a success. */
R_TRY_CATCH(this->ProcessRequest(session, tls_message)) {
R_CONVERT(sf::impl::ResultRequestInvalidated, ResultSuccess());
} R_END_TRY_CATCH;
} else {
if (!session->m_has_received) {
R_TRY(this->ReceiveRequest(session, tls_message));
session->m_has_received = true;
}
R_TRY_CATCH(this->ProcessRequest(session, tls_message)) {
R_CATCH(sf::ResultRequestDeferred) { AMS_ABORT("Request Deferred on server which does not support deferral"); }
R_CATCH(sf::impl::ResultRequestInvalidated) { AMS_ABORT("Request Invalidated on server which does not support deferral"); }
} R_END_TRY_CATCH;
}
return ResultSuccess(); return ResultSuccess();
} }
@ -138,6 +151,7 @@ namespace ams::sf::hipc {
case UserDataTag::Server: case UserDataTag::Server:
return this->ProcessForServer(holder); return this->ProcessForServer(holder);
case UserDataTag::MitmServer: case UserDataTag::MitmServer:
AMS_ABORT_UNLESS(this->CanManageMitmServers());
return this->ProcessForMitmServer(holder); return this->ProcessForMitmServer(holder);
case UserDataTag::Session: case UserDataTag::Session:
return this->ProcessForSession(holder); return this->ProcessForSession(holder);

View file

@ -40,7 +40,9 @@ namespace ams::sf::hipc {
} }
Result ServerSession::ForwardRequest(const cmif::ServiceDispatchContext &ctx) const { Result ServerSession::ForwardRequest(const cmif::ServiceDispatchContext &ctx) const {
AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers());
AMS_ABORT_UNLESS(this->IsMitmSession()); AMS_ABORT_UNLESS(this->IsMitmSession());
/* TODO: Support non-TLS messages? */ /* TODO: Support non-TLS messages? */
AMS_ABORT_UNLESS(m_saved_message.GetPointer() != nullptr); AMS_ABORT_UNLESS(m_saved_message.GetPointer() != nullptr);
AMS_ABORT_UNLESS(m_saved_message.GetSize() == TlsMessageBufferSize); AMS_ABORT_UNLESS(m_saved_message.GetSize() == TlsMessageBufferSize);
@ -55,7 +57,7 @@ namespace ams::sf::hipc {
PreProcessCommandBufferForMitm(ctx, m_pointer_buffer, reinterpret_cast<uintptr_t>(message_buffer)); PreProcessCommandBufferForMitm(ctx, m_pointer_buffer, reinterpret_cast<uintptr_t>(message_buffer));
/* Dispatch forwards. */ /* Dispatch forwards. */
R_TRY(svc::SendSyncRequest(m_forward_service->session)); R_TRY(svc::SendSyncRequest(util::GetReference(m_forward_service)->session));
/* Parse, to ensure we catch any copy handles and close them. */ /* Parse, to ensure we catch any copy handles and close them. */
{ {
@ -114,6 +116,8 @@ namespace ams::sf::hipc {
} }
Result ServerSessionManager::RegisterMitmSessionImpl(ServerSession *session_memory, os::NativeHandle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) { Result ServerSessionManager::RegisterMitmSessionImpl(ServerSession *session_memory, os::NativeHandle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers());
/* Create session object. */ /* Create session object. */
std::construct_at(session_memory, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv)); std::construct_at(session_memory, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv));
@ -122,8 +126,8 @@ namespace ams::sf::hipc {
session_memory->m_saved_message = this->GetSessionSavedMessageBuffer(session_memory); session_memory->m_saved_message = this->GetSessionSavedMessageBuffer(session_memory);
/* Validate session pointer buffer. */ /* Validate session pointer buffer. */
AMS_ABORT_UNLESS(session_memory->m_pointer_buffer.GetSize() >= session_memory->m_forward_service->pointer_buffer_size); AMS_ABORT_UNLESS(session_memory->m_pointer_buffer.GetSize() >= util::GetReference(session_memory->m_forward_service)->pointer_buffer_size);
session_memory->m_pointer_buffer = cmif::PointerAndSize(session_memory->m_pointer_buffer.GetAddress(), session_memory->m_forward_service->pointer_buffer_size); session_memory->m_pointer_buffer = cmif::PointerAndSize(session_memory->m_pointer_buffer.GetAddress(), util::GetReference(session_memory->m_forward_service)->pointer_buffer_size);
/* Register to wait list. */ /* Register to wait list. */
this->RegisterServerSessionToWait(session_memory); this->RegisterServerSessionToWait(session_memory);
@ -131,6 +135,8 @@ namespace ams::sf::hipc {
} }
Result ServerSessionManager::AcceptMitmSessionImpl(ServerSession *session_memory, os::NativeHandle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) { Result ServerSessionManager::AcceptMitmSessionImpl(ServerSession *session_memory, os::NativeHandle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers());
/* Create session handle. */ /* Create session handle. */
os::NativeHandle mitm_session_handle; os::NativeHandle mitm_session_handle;
R_TRY(svc::AcceptSession(std::addressof(mitm_session_handle), mitm_port_handle)); R_TRY(svc::AcceptSession(std::addressof(mitm_session_handle), mitm_port_handle));
@ -201,7 +207,7 @@ namespace ams::sf::hipc {
namespace { namespace {
NX_CONSTEXPR u32 GetCmifCommandType(const cmif::PointerAndSize &message) { constexpr ALWAYS_INLINE u32 GetCmifCommandType(const cmif::PointerAndSize &message) {
HipcHeader hdr = {}; HipcHeader hdr = {};
__builtin_memcpy(std::addressof(hdr), message.GetPointer(), sizeof(hdr)); __builtin_memcpy(std::addressof(hdr), message.GetPointer(), sizeof(hdr));
return hdr.type; return hdr.type;

View file

@ -41,9 +41,11 @@ namespace ams::sprofile::srv {
constexpr inline size_t PortCountMax = 2; constexpr inline size_t PortCountMax = 2;
struct ServerManagerOptions { struct ServerManagerOptions {
static constexpr size_t PointerBufferSize = 0x0; static constexpr size_t PointerBufferSize = 0x0;
static constexpr size_t MaxDomains = SessionCountMax; /* NOTE: Official is 3 */ static constexpr size_t MaxDomains = SessionCountMax; /* NOTE: Official is 3 */
static constexpr size_t MaxDomainObjects = 16; /* NOTE: Official is 8 */ static constexpr size_t MaxDomainObjects = 16; /* NOTE: Official is 8 */
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
}; };
using ServerManager = sf::hipc::ServerManager<PortCountMax, ServerManagerOptions, SessionCountMax>; using ServerManager = sf::hipc::ServerManager<PortCountMax, ServerManagerOptions, SessionCountMax>;

View file

@ -32,7 +32,14 @@ namespace ams::mitm::bpc {
constexpr size_t MitmServiceMaxSessions = 13; constexpr size_t MitmServiceMaxSessions = 13;
constexpr size_t MaxSessions = MitmServiceMaxSessions; constexpr size_t MaxSessions = MitmServiceMaxSessions;
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
struct ServerOptions {
static constexpr size_t PointerBufferSize = sf::hipc::DefaultServerManagerOptions::PointerBufferSize;
static constexpr size_t MaxDomains = sf::hipc::DefaultServerManagerOptions::MaxDomains;
static constexpr size_t MaxDomainObjects = sf::hipc::DefaultServerManagerOptions::MaxDomainObjects;
static constexpr bool CanDeferInvokeRequest = sf::hipc::DefaultServerManagerOptions::CanDeferInvokeRequest;
static constexpr bool CanManageMitmServers = true;
};
class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> { class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> {
private: private:

View file

@ -32,7 +32,14 @@ namespace ams::mitm::socket::resolver {
constexpr sm::ServiceName DnsMitmServiceName = sm::ServiceName::Encode("sfdnsres"); constexpr sm::ServiceName DnsMitmServiceName = sm::ServiceName::Encode("sfdnsres");
constexpr size_t MaxSessions = 30; constexpr size_t MaxSessions = 30;
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
struct ServerOptions {
static constexpr size_t PointerBufferSize = sf::hipc::DefaultServerManagerOptions::PointerBufferSize;
static constexpr size_t MaxDomains = sf::hipc::DefaultServerManagerOptions::MaxDomains;
static constexpr size_t MaxDomainObjects = sf::hipc::DefaultServerManagerOptions::MaxDomainObjects;
static constexpr bool CanDeferInvokeRequest = sf::hipc::DefaultServerManagerOptions::CanDeferInvokeRequest;
static constexpr bool CanManageMitmServers = true;
};
class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> { class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> {
private: private:

View file

@ -29,9 +29,11 @@ namespace ams::mitm::fs {
constexpr sm::ServiceName MitmServiceName = sm::ServiceName::Encode("fsp-srv"); constexpr sm::ServiceName MitmServiceName = sm::ServiceName::Encode("fsp-srv");
struct ServerOptions { struct ServerOptions {
static constexpr size_t PointerBufferSize = 0x800; static constexpr size_t PointerBufferSize = 0x800;
static constexpr size_t MaxDomains = 0x40; static constexpr size_t MaxDomains = 0x40;
static constexpr size_t MaxDomainObjects = 0x4000; static constexpr size_t MaxDomainObjects = 0x4000;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = true;
}; };
constexpr size_t MaxSessions = 61; constexpr size_t MaxSessions = 61;

View file

@ -32,7 +32,14 @@ namespace ams::mitm::ns {
constexpr sm::ServiceName NsWebMitmServiceName = sm::ServiceName::Encode("ns:web"); constexpr sm::ServiceName NsWebMitmServiceName = sm::ServiceName::Encode("ns:web");
constexpr size_t MaxSessions = 5; constexpr size_t MaxSessions = 5;
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
struct ServerOptions {
static constexpr size_t PointerBufferSize = sf::hipc::DefaultServerManagerOptions::PointerBufferSize;
static constexpr size_t MaxDomains = sf::hipc::DefaultServerManagerOptions::MaxDomains;
static constexpr size_t MaxDomainObjects = sf::hipc::DefaultServerManagerOptions::MaxDomainObjects;
static constexpr bool CanDeferInvokeRequest = sf::hipc::DefaultServerManagerOptions::CanDeferInvokeRequest;
static constexpr bool CanManageMitmServers = true;
};
class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> { class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> {
private: private:

View file

@ -33,9 +33,11 @@ namespace ams::mitm::settings {
constexpr sm::ServiceName SetSysMitmServiceName = sm::ServiceName::Encode("set:sys"); constexpr sm::ServiceName SetSysMitmServiceName = sm::ServiceName::Encode("set:sys");
struct ServerOptions { struct ServerOptions {
static constexpr size_t PointerBufferSize = 0x200; static constexpr size_t PointerBufferSize = 0x200;
static constexpr size_t MaxDomains = 0; static constexpr size_t MaxDomains = 0;
static constexpr size_t MaxDomainObjects = 0; static constexpr size_t MaxDomainObjects = 0;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = true;
}; };
constexpr size_t MaxSessions = 60; constexpr size_t MaxSessions = 60;

View file

@ -34,9 +34,11 @@ namespace ams::mitm::sysupdater {
constexpr size_t MaxSessions = SystemUpdateMaxSessions + 3; constexpr size_t MaxSessions = SystemUpdateMaxSessions + 3;
struct ServerOptions { struct ServerOptions {
static constexpr size_t PointerBufferSize = 1_KB; static constexpr size_t PointerBufferSize = 1_KB;
static constexpr size_t MaxDomains = 0; static constexpr size_t MaxDomains = 0;
static constexpr size_t MaxDomainObjects = 0; static constexpr size_t MaxDomainObjects = 0;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
}; };
sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> g_server_manager; sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> g_server_manager;

View file

@ -46,9 +46,11 @@ namespace ams {
namespace { namespace {
struct ServerOptions { struct ServerOptions {
static constexpr size_t PointerBufferSize = 0x400; static constexpr size_t PointerBufferSize = 0x400;
static constexpr size_t MaxDomains = 0; static constexpr size_t MaxDomains = 0;
static constexpr size_t MaxDomainObjects = 0; static constexpr size_t MaxDomainObjects = 0;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
}; };
/* ldr:pm, ldr:shel, ldr:dmnt. */ /* ldr:pm, ldr:shel, ldr:dmnt. */

View file

@ -45,9 +45,11 @@ namespace ams {
namespace { namespace {
struct ContentManagerServerOptions { struct ContentManagerServerOptions {
static constexpr size_t PointerBufferSize = 0x400; static constexpr size_t PointerBufferSize = 0x400;
static constexpr size_t MaxDomains = 0; static constexpr size_t MaxDomains = 0;
static constexpr size_t MaxDomainObjects = 0; static constexpr size_t MaxDomainObjects = 0;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
}; };
constexpr inline size_t ContentManagerNumServers = 1; constexpr inline size_t ContentManagerNumServers = 1;
@ -90,9 +92,11 @@ namespace ams {
}; };
struct LocationResolverServerOptions { struct LocationResolverServerOptions {
static constexpr size_t PointerBufferSize = 0x400; static constexpr size_t PointerBufferSize = 0x400;
static constexpr size_t MaxDomains = 0; static constexpr size_t MaxDomains = 0;
static constexpr size_t MaxDomainObjects = 0; static constexpr size_t MaxDomainObjects = 0;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
}; };
constexpr inline size_t LocationResolverNumServers = 1; constexpr inline size_t LocationResolverNumServers = 1;

View file

@ -32,9 +32,11 @@ namespace ams {
namespace { namespace {
struct SplServerOptions { struct SplServerOptions {
static constexpr size_t PointerBufferSize = 0x800; static constexpr size_t PointerBufferSize = 0x800;
static constexpr size_t MaxDomains = 0; static constexpr size_t MaxDomains = 0;
static constexpr size_t MaxDomainObjects = 0; static constexpr size_t MaxDomainObjects = 0;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
}; };
enum PortIndex { enum PortIndex {