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 MaxDomains = 6;
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> {

View file

@ -24,6 +24,8 @@ namespace ams::sf::hipc {
static constexpr size_t PointerBufferSize = 0;
static constexpr size_t MaxDomains = 0;
static constexpr size_t MaxDomainObjects = 0;
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
};
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));
}
};
protected:
static constinit inline bool g_is_any_deferred_supported = false;
static constinit inline bool g_is_any_mitm_supported = false;
private:
/* Multiple wait management. */
os::MultiWaitType m_multi_wait;
@ -84,6 +89,10 @@ namespace ams::sf::hipc {
os::SdkMutex m_deferred_list_mutex;
os::MultiWaitType m_deferred_list;
/* Boolean values. */
const bool m_is_defer_supported;
const bool m_is_mitm_supported;
private:
virtual void RegisterServerSessionToWait(ServerSession *session) override final;
void LinkToDeferredList(os::MultiWaitHolderType *holder);
@ -102,6 +111,7 @@ namespace ams::sf::hipc {
server->m_is_mitm_server = is_mitm_server;
if (is_mitm_server) {
/* Mitm server. */
AMS_ABORT_UNLESS(this->CanManageMitmServers());
os::SetMultiWaitHolderUserData(server, static_cast<uintptr_t>(UserDataTag::MitmServer));
} else {
/* Non-mitm server. */
@ -148,6 +158,26 @@ namespace ams::sf::hipc {
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>
Result RegisterMitmServerImpl(int index, cmif::ServiceObjectHolder &&static_holder, sm::ServiceName service_name) {
/* Install mitm service. */
@ -170,30 +200,11 @@ namespace ams::sf::hipc {
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:
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),
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. */
os::InitializeMultiWait(std::addressof(m_multi_wait));
@ -205,6 +216,22 @@ namespace ams::sf::hipc {
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>
void RegisterObjectForServer(SharedPointer<Interface> static_object, os::NativeHandle port_handle) {
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);
}
template<typename Interface>
Result RegisterMitmServer(int port_index, sm::ServiceName service_name) {
return this->template RegisterMitmServerImpl<Interface>(port_index, cmif::ServiceObjectHolder(), service_name);
}
/* Processing. */
os::MultiWaitHolderType *WaitSignaled();
@ -267,7 +289,7 @@ namespace ams::sf::hipc {
util::TypedStorage<ServerSession> m_session_storages[MaxSessions];
bool m_session_allocated[MaxSessions];
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_saved_messages_start;
@ -337,12 +359,16 @@ namespace ams::sf::hipc {
os::UnlinkMultiWaitHolder(server);
os::FinalizeMultiWaitHolder(server);
if (server->m_service_managed) {
if (server->m_is_mitm_server) {
R_ABORT_UNLESS(sm::mitm::UninstallMitm(server->m_service_name));
if constexpr (ManagerOptions::CanManageMitmServers) {
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 {
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;
@ -377,10 +403,14 @@ namespace ams::sf::hipc {
}
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:
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. */
#define SF_SM_MEMCLEAR(obj) if constexpr (sizeof(obj) > 0) { std::memset(obj, 0, sizeof(obj)); }
SF_SM_MEMCLEAR(m_server_storages);
@ -395,6 +425,14 @@ namespace ams::sf::hipc {
/* Set resource starts. */
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);
/* 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() {
@ -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::PointerAndSize m_pointer_buffer;
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;
bool m_is_closed;
bool m_has_received;
const bool m_has_forward_service;
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);
m_is_closed = false;
m_has_received = false;
m_forward_service = nullptr;
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);
m_is_closed = false;
m_has_received = false;
m_forward_service = std::move(fsrv);
AMS_ABORT_UNLESS(this->IsMitmSession());
util::ConstructAt(m_forward_service, std::move(fsrv));
AMS_ABORT_UNLESS(util::GetReference(m_forward_service) != nullptr);
}
bool IsMitmSession() const {
return m_forward_service != nullptr;
ALWAYS_INLINE bool IsMitmSession() const {
return m_has_forward_service;
}
Result ForwardRequest(const cmif::ServiceDispatchContext &ctx) const;