mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-03 08:08:39 -04:00
sf: prevent emitting mitm/defer code unless server in process supports it
This commit is contained in:
parent
d27fe8a229
commit
bd1bcdf52b
21 changed files with 230 additions and 107 deletions
|
@ -27,7 +27,7 @@ namespace ams::sf::hipc::impl {
|
|||
|
||||
class MitmQueryService {
|
||||
private:
|
||||
ServerManagerBase::MitmQueryFunction m_query_function;
|
||||
const ServerManagerBase::MitmQueryFunction m_query_function;
|
||||
public:
|
||||
MitmQueryService(ServerManagerBase::MitmQueryFunction qf) : m_query_function(qf) { /* ... */ }
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace ams::sf::hipc {
|
|||
private:
|
||||
ServerDomainSessionManager *m_manager;
|
||||
ServerSession *m_session;
|
||||
bool m_is_mitm_session;
|
||||
const bool m_is_mitm_session;
|
||||
private:
|
||||
Result CloneCurrentObjectImpl(sf::OutMoveHandle &out_client_handle, ServerSessionManager *tagged_manager) {
|
||||
/* Clone the object. */
|
||||
|
@ -47,9 +47,12 @@ namespace ams::sf::hipc {
|
|||
if (!m_is_mitm_session) {
|
||||
R_ABORT_UNLESS(tagged_manager->RegisterSession(server_handle, std::move(clone)));
|
||||
} else {
|
||||
/* Check that we can create a mitm session. */
|
||||
AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers());
|
||||
|
||||
/* Clone the forward service. */
|
||||
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)));
|
||||
}
|
||||
|
||||
|
@ -58,7 +61,7 @@ namespace ams::sf::hipc {
|
|||
return ResultSuccess();
|
||||
}
|
||||
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. */
|
||||
cmif::DomainObjectId object_id = cmif::InvalidDomainObjectId;
|
||||
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. */
|
||||
SharedPointer<cmif::MitmDomainServiceObject> cmif_domain(static_cast<cmif::MitmDomainServiceObject *>(domain), false);
|
||||
|
||||
/* Convert the remote session to domain. */
|
||||
AMS_ABORT_UNLESS(m_session->m_forward_service->own_handle);
|
||||
R_TRY(serviceConvertToDomain(m_session->m_forward_service.get()));
|
||||
AMS_ABORT_UNLESS(util::GetReference(m_session->m_forward_service)->own_handle);
|
||||
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. */
|
||||
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);
|
||||
|
||||
/* Register the object. */
|
||||
|
@ -116,14 +122,17 @@ namespace ams::sf::hipc {
|
|||
if (!object) {
|
||||
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;
|
||||
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);
|
||||
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. */
|
||||
os::NativeHandle server_handle, 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. */
|
||||
out.SetValue(client_handle, false);
|
||||
} else {
|
||||
/* Check that we can create a mitm session. */
|
||||
AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers());
|
||||
|
||||
/* Copy from the target domain. */
|
||||
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. */
|
||||
os::NativeHandle server_handle, client_handle;
|
||||
|
|
|
@ -114,21 +114,34 @@ namespace ams::sf::hipc {
|
|||
ServerSession *session = static_cast<ServerSession *>(holder);
|
||||
|
||||
cmif::PointerAndSize tls_message(svc::GetThreadLocalRegion()->message_buffer, hipc::TlsMessageBufferSize);
|
||||
const cmif::PointerAndSize &saved_message = session->m_saved_message;
|
||||
AMS_ABORT_UNLESS(tls_message.GetSize() == saved_message.GetSize());
|
||||
if (!session->m_has_received) {
|
||||
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());
|
||||
}
|
||||
if (this->CanDeferInvokeRequest()) {
|
||||
const cmif::PointerAndSize &saved_message = session->m_saved_message;
|
||||
AMS_ABORT_UNLESS(tls_message.GetSize() == saved_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;
|
||||
if (!session->m_has_received) {
|
||||
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. */
|
||||
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();
|
||||
}
|
||||
|
@ -138,6 +151,7 @@ namespace ams::sf::hipc {
|
|||
case UserDataTag::Server:
|
||||
return this->ProcessForServer(holder);
|
||||
case UserDataTag::MitmServer:
|
||||
AMS_ABORT_UNLESS(this->CanManageMitmServers());
|
||||
return this->ProcessForMitmServer(holder);
|
||||
case UserDataTag::Session:
|
||||
return this->ProcessForSession(holder);
|
||||
|
|
|
@ -40,7 +40,9 @@ namespace ams::sf::hipc {
|
|||
}
|
||||
|
||||
Result ServerSession::ForwardRequest(const cmif::ServiceDispatchContext &ctx) const {
|
||||
AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers());
|
||||
AMS_ABORT_UNLESS(this->IsMitmSession());
|
||||
|
||||
/* TODO: Support non-TLS messages? */
|
||||
AMS_ABORT_UNLESS(m_saved_message.GetPointer() != nullptr);
|
||||
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));
|
||||
|
||||
/* 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. */
|
||||
{
|
||||
|
@ -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) {
|
||||
AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers());
|
||||
|
||||
/* Create session object. */
|
||||
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);
|
||||
|
||||
/* Validate session pointer buffer. */
|
||||
AMS_ABORT_UNLESS(session_memory->m_pointer_buffer.GetSize() >= 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);
|
||||
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(), util::GetReference(session_memory->m_forward_service)->pointer_buffer_size);
|
||||
|
||||
/* Register to wait list. */
|
||||
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) {
|
||||
AMS_ABORT_UNLESS(ServerManagerBase::CanAnyManageMitmServers());
|
||||
|
||||
/* Create session handle. */
|
||||
os::NativeHandle mitm_session_handle;
|
||||
R_TRY(svc::AcceptSession(std::addressof(mitm_session_handle), mitm_port_handle));
|
||||
|
@ -201,7 +207,7 @@ namespace ams::sf::hipc {
|
|||
|
||||
namespace {
|
||||
|
||||
NX_CONSTEXPR u32 GetCmifCommandType(const cmif::PointerAndSize &message) {
|
||||
constexpr ALWAYS_INLINE u32 GetCmifCommandType(const cmif::PointerAndSize &message) {
|
||||
HipcHeader hdr = {};
|
||||
__builtin_memcpy(std::addressof(hdr), message.GetPointer(), sizeof(hdr));
|
||||
return hdr.type;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue