sm: fix deadlock semantics surrounding mitm installation

This commit is contained in:
Michael Scire 2020-09-07 10:40:43 -07:00
parent fac502aaa3
commit 99b5458539
10 changed files with 62 additions and 3 deletions

View file

@ -588,6 +588,15 @@ namespace ams::sm::impl {
*out = INVALID_HANDLE;
*out_query = INVALID_HANDLE;
/* If we don't have a future mitm declaration, add one. */
/* Client will clear this when ready to process. */
bool has_existing_future_declaration = HasFutureMitmDeclaration(service);
if (!has_existing_future_declaration) {
R_TRY(AddFutureMitmDeclaration(service));
}
auto future_guard = SCOPE_GUARD { if (!has_existing_future_declaration) { ClearFutureMitmDeclaration(service); } };
/* Create mitm handles. */
{
os::ManagedHandle hnd, port_hnd, qry_hnd, mitm_qry_hnd;
@ -603,9 +612,7 @@ namespace ams::sm::impl {
*out_query = qry_hnd.Move();
}
/* Clear the future declaration, if one exists. */
ClearFutureMitmDeclaration(service);
future_guard.Cancel();
return ResultSuccess();
}
@ -651,6 +658,34 @@ namespace ams::sm::impl {
return ResultSuccess();
}
Result ClearFutureMitm(os::ProcessId process_id, ServiceName service) {
/* Validate service name. */
R_TRY(ValidateServiceName(service));
/* Check that the process is registered and allowed to register the service. */
if (!IsInitialProcess(process_id)) {
ProcessInfo *proc = GetProcessInfo(process_id);
R_UNLESS(proc != nullptr, sm::ResultInvalidClient());
R_TRY(ValidateAccessControl(AccessControlEntry(proc->access_control, proc->access_control_size), service, true, false));
}
/* Check that a future mitm declaration is present or we have a mitm. */
if (HasMitm(service)) {
/* Validate that the service exists. */
ServiceInfo *service_info = GetServiceInfo(service);
R_UNLESS(service_info != nullptr, sm::ResultNotRegistered());
/* Validate that the client process_id is the mitm process. */
R_UNLESS(service_info->mitm_process_id == process_id, sm::ResultNotAllowed());
} else {
R_UNLESS(HasFutureMitmDeclaration(service), sm::ResultNotRegistered());
}
/* Clear the forward declaration. */
ClearFutureMitmDeclaration(service);
return ResultSuccess();
}
Result AcknowledgeMitmSession(MitmProcessInfo *out_info, Handle *out_hnd, os::ProcessId process_id, ServiceName service) {
/* Validate service name. */
R_TRY(ValidateServiceName(service));

View file

@ -37,6 +37,7 @@ namespace ams::sm::impl {
Result InstallMitm(Handle *out, Handle *out_query, os::ProcessId process_id, ServiceName service);
Result UninstallMitm(os::ProcessId process_id, ServiceName service);
Result DeclareFutureMitm(os::ProcessId process_id, ServiceName service);
Result ClearFutureMitm(os::ProcessId process_id, ServiceName service);
Result AcknowledgeMitmSession(MitmProcessInfo *out_info, Handle *out_hnd, os::ProcessId process_id, ServiceName service);
/* Dmnt record extensions. */

View file

@ -75,6 +75,11 @@ namespace ams::sm {
return impl::DeclareFutureMitm(this->process_id, service);
}
Result UserService::AtmosphereClearFutureMitm(ServiceName service) {
R_TRY(this->EnsureInitialized());
return impl::ClearFutureMitm(this->process_id, service);
}
Result UserService::AtmosphereHasService(sf::Out<bool> out, ServiceName service) {
R_TRY(this->EnsureInitialized());

View file

@ -40,6 +40,7 @@ namespace ams::sm {
Result AtmosphereHasMitm(sf::Out<bool> out, ServiceName service);
Result AtmosphereWaitMitm(ServiceName service);
Result AtmosphereDeclareFutureMitm(ServiceName service);
Result AtmosphereClearFutureMitm(ServiceName service);
Result AtmosphereHasService(sf::Out<bool> out, ServiceName service);
Result AtmosphereWaitService(ServiceName service);