1
0
Fork 0
mirror of https://github.com/Atmosphere-NX/Atmosphere.git synced 2024-11-23 04:12:02 +00:00

fs.mitm: Add domain support (closes #202)

This commit is contained in:
Michael Scire 2018-10-16 13:33:45 -07:00
parent 9ae62a27dd
commit f603dbfc98
6 changed files with 66 additions and 178 deletions

View file

@ -17,47 +17,6 @@
#include <switch.h> #include <switch.h>
#include "fs_shim.h" #include "fs_shim.h"
/* Necessary evil. */
Result ipcCopyFromDomain(Handle session, u32 object_id, Service *out) {
u32* buf = (u32*)armGetTls();
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u32 object_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
buf[0] = IpcCommandType_Control;
raw->magic = SFCI_MAGIC;
raw->cmd_id = 1;
raw->object_id = object_id;
Result rc = ipcDispatch(session);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct ipcCopyFromDomainResponse {
u64 magic;
u64 result;
} *raw = (struct ipcCopyFromDomainResponse*)r.Raw;
rc = raw->result;
if (R_SUCCEEDED(rc)) {
serviceCreate(out, r.Handles[0]);
}
}
return rc;
}
/* Missing fsp-srv commands. */ /* Missing fsp-srv commands. */
Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) { Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) {
IpcCommand c; IpcCommand c;
@ -68,7 +27,7 @@ Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) {
u64 cmd_id; u64 cmd_id;
} *raw; } *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 200; raw->cmd_id = 200;
@ -77,60 +36,25 @@ Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) {
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;
ipcParse(&r);
struct { struct {
u64 magic; u64 magic;
u64 result; u64 result;
} *resp = r.Raw; } *resp;
serviceIpcParse(s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result; rc = resp->result;
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
serviceCreate(&out->s, r.Handles[0]); serviceCreateSubservice(&out->s, s, &r, 0);
} }
} }
return rc; return rc;
} }
Result fsOpenDataStorageByCurrentProcessFromDomainFwd(Service* s, u32 *out_object_id) { Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), s->object_id);
raw->magic = SFCI_MAGIC;
raw->cmd_id = 200;
Result rc = serviceIpcDispatch(s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParseForDomain(&r);
struct {
u64 magic;
u64 result;
u32 object_id;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*out_object_id = resp->object_id;
}
}
return rc;
}
Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
@ -141,7 +65,7 @@ Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id
u64 data_id; u64 data_id;
} *raw; } *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 202; raw->cmd_id = 202;
@ -152,58 +76,18 @@ Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;
ipcParse(&r);
struct { struct {
u64 magic; u64 magic;
u64 result; u64 result;
} *resp = r.Raw; } *resp;
serviceIpcParse(s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result; rc = resp->result;
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
serviceCreate(&out->s, r.Handles[0]); serviceCreateSubservice(&out->s, s, &r, 0);
}
}
return rc;
}
Result fsOpenDataStorageByDataIdFromDomain(Service* s, FsStorageId storage_id, u64 data_id, u32 *out_object_id) {
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
FsStorageId storage_id;
u64 data_id;
} *raw;
raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), s->object_id);
raw->magic = SFCI_MAGIC;
raw->cmd_id = 202;
raw->storage_id = storage_id;
raw->data_id = data_id;
Result rc = serviceIpcDispatch(s);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParseForDomain(&r);
struct {
u64 magic;
u64 result;
u32 object_id;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*out_object_id = resp->object_id;
} }
} }
@ -223,7 +107,7 @@ Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *o
u64 len; u64 len;
} *raw; } *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = serviceIpcPrepareHeader(&f->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 5; raw->cmd_id = 5;
@ -235,13 +119,14 @@ Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *o
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;
ipcParse(&r);
struct { struct {
u64 magic; u64 magic;
u64 result; u64 result;
FsRangeInfo range_info; FsRangeInfo range_info;
} *resp = r.Raw; } *resp;
serviceIpcParse(&f->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result; rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->range_info; if (R_SUCCEEDED(rc) && out) *out = resp->range_info;
@ -263,7 +148,7 @@ Result fsStorageOperateRange(FsStorage* s, u32 op_id, u64 off, u64 len, FsRangeI
u64 len; u64 len;
} *raw; } *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw)); raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;
raw->cmd_id = 5; raw->cmd_id = 5;
@ -275,13 +160,14 @@ Result fsStorageOperateRange(FsStorage* s, u32 op_id, u64 off, u64 len, FsRangeI
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
IpcParsedCommand r; IpcParsedCommand r;
ipcParse(&r);
struct { struct {
u64 magic; u64 magic;
u64 result; u64 result;
FsRangeInfo range_info; FsRangeInfo range_info;
} *resp = r.Raw; } *resp;
serviceIpcParse(&s->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result; rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->range_info; if (R_SUCCEEDED(rc) && out) *out = resp->range_info;

View file

@ -16,14 +16,9 @@ typedef struct {
u32 flags[0x40/sizeof(u32)]; u32 flags[0x40/sizeof(u32)];
} FsRangeInfo; } FsRangeInfo;
/* Necessary evils. */
Result ipcCopyFromDomain(Handle session, u32 object_id, Service *out);
/* Missing fsp-srv commands. */ /* Missing fsp-srv commands. */
Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out); Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out);
Result fsOpenDataStorageByCurrentProcessFromDomainFwd(Service* s, u32 *out_object_id); Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out);
Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out);
Result fsOpenDataStorageByDataIdFromDomain(Service* s, FsStorageId storage_id, u64 data_id, u32 *out_object_id);
/* Missing FS File commands. */ /* Missing FS File commands. */
Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *out); Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *out);

View file

@ -91,7 +91,11 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora
Result rc; Result rc;
if (this->romfs_storage != nullptr) { if (this->romfs_storage != nullptr) {
if (this->get_owner() != NULL) { if (this->get_owner() != NULL) {
rc = fsOpenDataStorageByCurrentProcessFromDomainFwd(this->forward_service, &out_domain_id); FsStorage s = {0};
rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &s);
if (R_SUCCEEDED(rc)) {
out_domain_id = s.s.object_id;
}
} else { } else {
rc = 0; rc = 0;
} }
@ -102,15 +106,9 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora
} else { } else {
FsStorage data_storage; FsStorage data_storage;
FsFile data_file; FsFile data_file;
rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &data_storage);
if (this->get_owner() == NULL) {
rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &data_storage);
} else {
rc = fsOpenDataStorageByCurrentProcessFromDomainFwd(this->forward_service, &out_domain_id);
if (R_SUCCEEDED(rc)) {
rc = ipcCopyFromDomain(this->forward_service->handle, out_domain_id, &data_storage.s);
}
}
Log(armGetTls(), 0x100); Log(armGetTls(), 0x100);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
/* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */
@ -123,6 +121,8 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora
out_session = new IPCSession<IStorageInterface>(out_storage); out_session = new IPCSession<IStorageInterface>(out_storage);
if (this->get_owner() == NULL) { if (this->get_owner() == NULL) {
FsMitMWorker::AddWaitable(out_session); FsMitMWorker::AddWaitable(out_session);
} else {
out_domain_id = data_storage.s.object_id;
} }
} }
} }
@ -140,14 +140,9 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora
FsFile data_file; FsFile data_file;
u32 out_domain_id = 0; u32 out_domain_id = 0;
Result rc; Result rc;
if (this->get_owner() == NULL) {
rc = fsOpenDataStorageByDataId(this->forward_service, storage_id, data_id, &data_storage); rc = fsOpenDataStorageByDataIdFwd(this->forward_service, storage_id, data_id, &data_storage);
} else {
rc = fsOpenDataStorageByDataIdFromDomain(this->forward_service, storage_id, data_id, &out_domain_id);
if (R_SUCCEEDED(rc)) {
rc = ipcCopyFromDomain(this->forward_service->handle, out_domain_id, &data_storage.s);
}
}
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
/* TODO: Is there a sensible path that ends in ".romfs" we can use?" */ /* TODO: Is there a sensible path that ends in ".romfs" we can use?" */
if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) { if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) {
@ -157,6 +152,8 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora
} }
if (this->get_owner() == NULL) { if (this->get_owner() == NULL) {
FsMitMWorker::AddWaitable(out_session); FsMitMWorker::AddWaitable(out_session);
} else {
out_domain_id = data_storage.s.object_id;
} }
} }

View file

@ -87,20 +87,20 @@ class MitMSession final : public ISession<T> {
if (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext) { if (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext) {
std::shared_ptr<IServiceObject> obj; std::shared_ptr<IServiceObject> obj;
if (r.IsDomainMessage) { if (r.IsDomainRequest) {
obj = this->domain->get_domain_object(r.ThisObjectId); obj = this->domain->get_domain_object(r.InThisObjectId);
if (obj != nullptr && r.MessageType == DomainMessageType_Close) { if (obj != nullptr && r.InMessageType == DomainMessageType_Close) {
if (r.ThisObjectId == this->mitm_domain_id) { if (r.InThisObjectId == this->mitm_domain_id) {
Reboot(); Reboot();
} }
this->domain->delete_object(r.ThisObjectId); this->domain->delete_object(r.InThisObjectId);
struct { struct {
u64 magic; u64 magic;
u64 result; u64 result;
} *o_resp; } *o_resp;
o_resp = (decltype(o_resp)) ipcPrepareHeaderForDomain(&c, sizeof(*o_resp), 0); o_resp = (decltype(o_resp)) ipcPrepareHeaderForDomain(&c, sizeof(*o_resp), 0);
*(DomainMessageHeader *)((uintptr_t)o_resp - sizeof(DomainMessageHeader)) = {0}; *(DomainResponseHeader *)((uintptr_t)o_resp - sizeof(DomainResponseHeader)) = {0};
o_resp->magic = SFCO_MAGIC; o_resp->magic = SFCO_MAGIC;
o_resp->result = 0x0; o_resp->result = 0x0;
Log(armGetTls(), 0x100); Log(armGetTls(), 0x100);
@ -112,8 +112,9 @@ class MitMSession final : public ISession<T> {
if (obj != nullptr) { if (obj != nullptr) {
retval = obj->dispatch(r, c, cmd_id, (u8 *)this->pointer_buffer.data(), this->pointer_buffer.size()); retval = obj->dispatch(r, c, cmd_id, (u8 *)this->pointer_buffer.data(), this->pointer_buffer.size());
if (R_SUCCEEDED(retval)) { if (R_SUCCEEDED(retval)) {
if (r.IsDomainMessage) { if (r.IsDomainRequest) {
ipcParseForDomain(&cur_out_r); /* We never work with out object ids, so this should be fine. */
ipcParseDomainResponse(&cur_out_r, 0);
} else { } else {
ipcParse(&cur_out_r); ipcParse(&cur_out_r);
} }
@ -182,8 +183,9 @@ class MitMSession final : public ISession<T> {
Log(armGetTls(), 0x100); Log(armGetTls(), 0x100);
retval = serviceIpcDispatch(&forward_service); retval = serviceIpcDispatch(&forward_service);
if (R_SUCCEEDED(retval)) { if (R_SUCCEEDED(retval)) {
if (r.IsDomainMessage) { if (r.IsDomainRequest) {
ipcParseForDomain(&cur_out_r); /* We never work with out object ids, so this should be fine. */
ipcParseDomainResponse(&cur_out_r, 0);
} else { } else {
ipcParse(&cur_out_r); ipcParse(&cur_out_r);
} }

View file

@ -459,7 +459,9 @@ struct Encoder<std::tuple<Args...>> {
raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(*raw) + size_in_raw_data_for_arguments<Args... >::value - sizeof(Result)); raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(*raw) + size_in_raw_data_for_arguments<Args... >::value - sizeof(Result));
} else { } else {
raw = (decltype(raw))ipcPrepareHeaderForDomain(&out_command, sizeof(*raw) + size_in_raw_data_for_arguments<Args... >::value + (num_out_sessions_in_arguments<Args... >::value * sizeof(u32)) - sizeof(Result), 0); raw = (decltype(raw))ipcPrepareHeaderForDomain(&out_command, sizeof(*raw) + size_in_raw_data_for_arguments<Args... >::value + (num_out_sessions_in_arguments<Args... >::value * sizeof(u32)) - sizeof(Result), 0);
*((DomainMessageHeader *)((uintptr_t)raw - sizeof(DomainMessageHeader))) = {0}; auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader));
*resp_header = {0};
resp_header->NumObjectIds = num_out_sessions_in_arguments<Args... >::value;
} }
@ -474,7 +476,13 @@ struct Encoder<std::tuple<Args...>> {
if (R_FAILED(rc)) { if (R_FAILED(rc)) {
std::fill(tls, tls + 0x100, 0x00); std::fill(tls, tls + 0x100, 0x00);
ipcInitialize(&out_command); ipcInitialize(&out_command);
raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(raw)); if (domain_owner != NULL) {
raw = (decltype(raw))ipcPrepareHeaderForDomain(&out_command, sizeof(raw), 0);
auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader));
*resp_header = {0};
} else {
raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(raw));
}
raw->magic = SFCO_MAGIC; raw->magic = SFCO_MAGIC;
raw->result = rc; raw->result = rc;
} }
@ -526,7 +534,7 @@ Result WrapIpcCommandImpl(Class *this_ptr, IpcParsedCommand& r, IpcCommand &out_
auto args = Decoder<OutArgs, InArgsWithoutThis>::Decode(r, out_command, pointer_buffer); auto args = Decoder<OutArgs, InArgsWithoutThis>::Decode(r, out_command, pointer_buffer);
auto result = std::apply( [=](auto&&... args) { return (this_ptr->*IpcCommandImpl)(args...); }, args); auto result = std::apply( [=](auto&&... args) { return (this_ptr->*IpcCommandImpl)(args...); }, args);
DomainOwner *down = NULL; DomainOwner *down = NULL;
if (r.IsDomainMessage) { if (r.IsDomainRequest) {
down = this_ptr->get_owner(); down = this_ptr->get_owner();
} }

View file

@ -118,12 +118,12 @@ class ISession : public IWaitable {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
if (r.IsDomainMessage && this->active_object == NULL) { if (r.IsDomainRequest && this->active_object == NULL) {
return 0xF601; return 0xF601;
} }
if (r.IsDomainMessage && r.MessageType == DomainMessageType_Close) { if (r.IsDomainRequest && r.InMessageType == DomainMessageType_Close) {
this->domain->delete_object(this->active_object); this->domain->delete_object(this->active_object);
this->active_object = NULL; this->active_object = NULL;
struct { struct {
@ -198,11 +198,11 @@ class ISession : public IWaitable {
Result retval = ipcParse(&r); Result retval = ipcParse(&r);
if (R_SUCCEEDED(retval)) { if (R_SUCCEEDED(retval)) {
if (this->is_domain && (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext)) { if (this->is_domain && (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext)) {
retval = ipcParseForDomain(&r); retval = ipcParseDomainRequest(&r);
if (!r.IsDomainMessage || r.ThisObjectId >= DOMAIN_ID_MAX) { if (!r.IsDomainRequest || r.InThisObjectId >= DOMAIN_ID_MAX) {
retval = 0xF601; retval = 0xF601;
} else { } else {
this->active_object = this->domain->get_domain_object(r.ThisObjectId); this->active_object = this->domain->get_domain_object(r.InThisObjectId);
} }
} else { } else {
this->active_object = this->service_object; this->active_object = this->service_object;