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 "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. */
Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) {
IpcCommand c;
@ -68,7 +27,7 @@ Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) {
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 200;
@ -77,60 +36,25 @@ Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) {
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
} *resp;
serviceIpcParse(s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
serviceCreate(&out->s, r.Handles[0]);
serviceCreateSubservice(&out->s, s, &r, 0);
}
}
return rc;
}
Result fsOpenDataStorageByCurrentProcessFromDomainFwd(Service* s, u32 *out_object_id) {
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) {
Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out) {
IpcCommand c;
ipcInitialize(&c);
@ -141,7 +65,7 @@ Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id
u64 data_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 202;
@ -152,58 +76,18 @@ Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
} *resp;
serviceIpcParse(s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
serviceCreate(&out->s, r.Handles[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;
serviceCreateSubservice(&out->s, s, &r, 0);
}
}
@ -223,7 +107,7 @@ Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *o
u64 len;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw = serviceIpcPrepareHeader(&f->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
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)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
FsRangeInfo range_info;
} *resp = r.Raw;
} *resp;
serviceIpcParse(&f->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
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;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 5;
@ -275,13 +160,14 @@ Result fsStorageOperateRange(FsStorage* s, u32 op_id, u64 off, u64 len, FsRangeI
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
FsRangeInfo range_info;
} *resp = r.Raw;
} *resp;
serviceIpcParse(&s->s, &r, sizeof(*resp));
resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc) && out) *out = resp->range_info;

View file

@ -16,14 +16,9 @@ typedef struct {
u32 flags[0x40/sizeof(u32)];
} FsRangeInfo;
/* Necessary evils. */
Result ipcCopyFromDomain(Handle session, u32 object_id, Service *out);
/* Missing fsp-srv commands. */
Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out);
Result fsOpenDataStorageByCurrentProcessFromDomainFwd(Service* s, u32 *out_object_id);
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);
Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out);
/* Missing FS File commands. */
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;
if (this->romfs_storage != nullptr) {
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 {
rc = 0;
}
@ -102,15 +106,9 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora
} else {
FsStorage data_storage;
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);
if (R_SUCCEEDED(rc)) {
/* 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);
if (this->get_owner() == NULL) {
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;
u32 out_domain_id = 0;
Result rc;
if (this->get_owner() == NULL) {
rc = fsOpenDataStorageByDataId(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);
}
}
rc = fsOpenDataStorageByDataIdFwd(this->forward_service, storage_id, data_id, &data_storage);
if (R_SUCCEEDED(rc)) {
/* 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))) {
@ -157,6 +152,8 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora
}
if (this->get_owner() == NULL) {
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) {
std::shared_ptr<IServiceObject> obj;
if (r.IsDomainMessage) {
obj = this->domain->get_domain_object(r.ThisObjectId);
if (obj != nullptr && r.MessageType == DomainMessageType_Close) {
if (r.ThisObjectId == this->mitm_domain_id) {
if (r.IsDomainRequest) {
obj = this->domain->get_domain_object(r.InThisObjectId);
if (obj != nullptr && r.InMessageType == DomainMessageType_Close) {
if (r.InThisObjectId == this->mitm_domain_id) {
Reboot();
}
this->domain->delete_object(r.ThisObjectId);
this->domain->delete_object(r.InThisObjectId);
struct {
u64 magic;
u64 result;
} *o_resp;
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->result = 0x0;
Log(armGetTls(), 0x100);
@ -112,8 +112,9 @@ class MitMSession final : public ISession<T> {
if (obj != nullptr) {
retval = obj->dispatch(r, c, cmd_id, (u8 *)this->pointer_buffer.data(), this->pointer_buffer.size());
if (R_SUCCEEDED(retval)) {
if (r.IsDomainMessage) {
ipcParseForDomain(&cur_out_r);
if (r.IsDomainRequest) {
/* We never work with out object ids, so this should be fine. */
ipcParseDomainResponse(&cur_out_r, 0);
} else {
ipcParse(&cur_out_r);
}
@ -182,8 +183,9 @@ class MitMSession final : public ISession<T> {
Log(armGetTls(), 0x100);
retval = serviceIpcDispatch(&forward_service);
if (R_SUCCEEDED(retval)) {
if (r.IsDomainMessage) {
ipcParseForDomain(&cur_out_r);
if (r.IsDomainRequest) {
/* We never work with out object ids, so this should be fine. */
ipcParseDomainResponse(&cur_out_r, 0);
} else {
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));
} 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);
*((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)) {
std::fill(tls, tls + 0x100, 0x00);
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->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 result = std::apply( [=](auto&&... args) { return (this_ptr->*IpcCommandImpl)(args...); }, args);
DomainOwner *down = NULL;
if (r.IsDomainMessage) {
if (r.IsDomainRequest) {
down = this_ptr->get_owner();
}

View file

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