mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-05 19:51:45 +00:00
fs.mitm: Intercept OpenBisStorage calls.
This commit is contained in:
parent
66da896347
commit
d95fc102db
6 changed files with 165 additions and 28 deletions
|
@ -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);
|
||||
};
|
||||
};
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -79,6 +79,40 @@ void FsMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx
|
|||
}
|
||||
}
|
||||
|
||||
/* Gate access to the BIS partitions. */
|
||||
Result FsMitmService::OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out_storage, u32 bis_partition_id) {
|
||||
std::shared_ptr<IStorageInterface> 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<IStorageInterface>(new ROProxyStorage(bis_storage));
|
||||
} else {
|
||||
/* Sysmodules should still be allowed to read and write. */
|
||||
storage = std::make_shared<IStorageInterface>(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<std::shared_ptr<IStorageInterface>> out_storage) {
|
||||
std::shared_ptr<IStorageInterface> storage = nullptr;
|
||||
|
|
|
@ -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<std::shared_ptr<IStorageInterface>> out, u32 bis_partition_id);
|
||||
Result OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStorageInterface>> out);
|
||||
Result OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out, u64 data_id, u8 storage_id);
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MakeServiceCommandMeta<FspSrvCmd_OpenBisStorage, &FsMitmService::OpenBisStorage>(),
|
||||
MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByCurrentProcess, &FsMitmService::OpenDataStorageByCurrentProcess>(),
|
||||
MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByDataId, &FsMitmService::OpenDataStorageByDataId>(),
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue