diff --git a/stratosphere/fs_mitm/source/fs_istorage.hpp b/stratosphere/fs_mitm/source/fs_istorage.hpp index 2f21b6b7e..23233e27f 100644 --- a/stratosphere/fs_mitm/source/fs_istorage.hpp +++ b/stratosphere/fs_mitm/source/fs_istorage.hpp @@ -108,3 +108,65 @@ class IROStorage : public IStorage { virtual Result GetSize(u64 *out_size) = 0; virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) = 0; }; + + +class ProxyStorage : public IStorage { + private: + FsStorage *base_storage; + public: + ProxyStorage(FsStorage *s) : base_storage(s) { + /* ... */ + }; + ProxyStorage(FsStorage s) { + this->base_storage = new FsStorage(s); + }; + ~ProxyStorage() { + fsStorageClose(base_storage); + delete base_storage; + }; + public: + virtual Result Read(void *buffer, size_t size, u64 offset) override { + return fsStorageRead(this->base_storage, offset, buffer, size); + }; + virtual Result Write(void *buffer, size_t size, u64 offset) override { + return fsStorageWrite(this->base_storage, offset, buffer, size); + }; + virtual Result Flush() override { + return fsStorageFlush(this->base_storage); + }; + virtual Result GetSize(u64 *out_size) override { + return fsStorageGetSize(this->base_storage, out_size); + }; + virtual Result SetSize(u64 size) override { + return fsStorageSetSize(this->base_storage, size); + }; + virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override { + return fsStorageOperateRange(this->base_storage, operation_type, offset, size, out_range_info); + }; +}; + +class ROProxyStorage : public IROStorage { + private: + FsStorage *base_storage; + public: + ROProxyStorage(FsStorage *s) : base_storage(s) { + /* ... */ + }; + ROProxyStorage(FsStorage s) { + this->base_storage = new FsStorage(s); + }; + ~ROProxyStorage() { + fsStorageClose(base_storage); + delete base_storage; + }; + public: + virtual Result Read(void *buffer, size_t size, u64 offset) override { + return fsStorageRead(this->base_storage, offset, buffer, size); + }; + virtual Result GetSize(u64 *out_size) override { + return fsStorageGetSize(this->base_storage, out_size); + }; + virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override { + return fsStorageOperateRange(this->base_storage, operation_type, offset, size, out_range_info); + }; +}; \ No newline at end of file diff --git a/stratosphere/fs_mitm/source/fs_shim.c b/stratosphere/fs_mitm/source/fs_shim.c index 134d83498..915366bb8 100644 --- a/stratosphere/fs_mitm/source/fs_shim.c +++ b/stratosphere/fs_mitm/source/fs_shim.c @@ -18,6 +18,44 @@ #include "fs_shim.h" /* Missing fsp-srv commands. */ +Result fsOpenBisStorageFwd(Service* s, FsStorage* out, u32 PartitionId) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 PartitionId; + } *raw; + + raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 12; + raw->PartitionId = PartitionId; + + Result rc = serviceIpcDispatch(s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreateSubservice(&out->s, s, &r, 0); + } + } + + return rc; +} + Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) { IpcCommand c; ipcInitialize(&c); diff --git a/stratosphere/fs_mitm/source/fs_shim.h b/stratosphere/fs_mitm/source/fs_shim.h index d73c2595b..730a2bfb5 100644 --- a/stratosphere/fs_mitm/source/fs_shim.h +++ b/stratosphere/fs_mitm/source/fs_shim.h @@ -17,6 +17,7 @@ typedef struct { } FsRangeInfo; /* Missing fsp-srv commands. */ +Result fsOpenBisStorageFwd(Service* s, FsStorage* out, u32 PartitionId); Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out); Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out); diff --git a/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp b/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp index c421a2147..04d0cf8d6 100644 --- a/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_romstorage.hpp @@ -54,30 +54,4 @@ class RomFileStorage : public IROStorage { }; /* Represents a RomFS accessed via some IStorage. */ -class RomInterfaceStorage : public IROStorage { - private: - FsStorage *base_storage; - public: - RomInterfaceStorage(FsStorage *s) : base_storage(s) { - /* ... */ - }; - RomInterfaceStorage(FsStorage s) { - this->base_storage = new FsStorage(s); - }; - ~RomInterfaceStorage() { - fsStorageClose(base_storage); - delete base_storage; - }; - public: - Result Read(void *buffer, size_t size, u64 offset) override { - return fsStorageRead(this->base_storage, offset, buffer, size); - }; - Result GetSize(u64 *out_size) override { - /* TODO: Merge into libnx? */ - return fsStorageGetSize(this->base_storage, out_size); - }; - Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) override { - /* TODO: Merge into libnx? */ - return fsStorageOperateRange(this->base_storage, operation_type, offset, size, out_range_info); - }; -}; +using RomInterfaceStorage = ROProxyStorage; diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index 91364ae19..505af638b 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -79,6 +79,40 @@ void FsMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx } } +/* Gate access to the BIS partitions. */ +Result FsMitmService::OpenBisStorage(Out> out_storage, u32 bis_partition_id) { + std::shared_ptr storage = nullptr; + u32 out_domain_id = 0; + Result rc = 0; + + ON_SCOPE_EXIT { + if (R_SUCCEEDED(rc)) { + out_storage.SetValue(std::move(storage)); + if (out_storage.IsDomain()) { + out_storage.ChangeObjectId(out_domain_id); + } + } + }; + + { + FsStorage bis_storage; + rc = fsOpenBisStorageFwd(this->forward_service.get(), &bis_storage, bis_partition_id); + if (R_SUCCEEDED(rc)) { + if (this->title_id >= 0x0100000000001000) { + storage = std::make_shared(new ROProxyStorage(bis_storage)); + } else { + /* Sysmodules should still be allowed to read and write. */ + storage = std::make_shared(new ProxyStorage(bis_storage)); + } + if (out_storage.IsDomain()) { + out_domain_id = bis_storage.s.object_id; + } + } + } + + return rc; +} + /* Add redirection for RomFS to the SD card. */ Result FsMitmService::OpenDataStorageByCurrentProcess(Out> out_storage) { std::shared_ptr storage = nullptr; diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 2fffacfa9..07fb38398 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -22,11 +22,31 @@ enum FspSrvCmd : u32 { FspSrvCmd_SetCurrentProcess = 1, + FspSrvCmd_OpenBisStorage = 12, FspSrvCmd_OpenDataStorageByCurrentProcess = 200, FspSrvCmd_OpenDataStorageByDataId = 202, }; -class FsMitmService : public IMitmServiceObject { +enum BisStorageId : u32 { + BisStorageId_Boot0 = 0, + BisStorageId_Boot1 = 10, + BisStorageId_RawNand = 20, + BisStorageId_BcPkg2_1 = 21, + BisStorageId_BcPkg2_2 = 22, + BisStorageId_BcPkg2_3 = 23, + BisStorageId_BcPkg2_4 = 24, + BisStorageId_BcPkg2_5 = 25, + BisStorageId_BcPkg2_6 = 26, + BisStorageId_Prodinfo = 27, + BisStorageId_ProdinfoF = 28, + BisStorageId_Safe = 29, + BisStorageId_User = 30, + BisStorageId_System = 31, + BisStorageId_SystemProperEncryption = 32, + BisStorageId_SystemProperPartition = 33, +}; + +class FsMitmService : public IMitmServiceObject { private: bool has_initialized = false; public: @@ -35,9 +55,15 @@ class FsMitmService : public IMitmServiceObject { } static bool ShouldMitm(u64 pid, u64 tid) { + /* Always intercept NS, so that we can protect the boot partition. */ + if (tid == 0x010000000000001FULL) { + return true; + } + if (Utils::HasSdDisableMitMFlag(tid)) { return false; } + return (tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid)) && Utils::HasOverrideButton(tid); } @@ -45,10 +71,12 @@ class FsMitmService : public IMitmServiceObject { protected: /* Overridden commands. */ + Result OpenBisStorage(Out> out, u32 bis_partition_id); Result OpenDataStorageByCurrentProcess(Out> out); Result OpenDataStorageByDataId(Out> out, u64 data_id, u8 storage_id); public: DEFINE_SERVICE_DISPATCH_TABLE { + MakeServiceCommandMeta(), MakeServiceCommandMeta(), MakeServiceCommandMeta(), };