mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-06 04:01:44 +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 GetSize(u64 *out_size) = 0;
|
||||||
virtual Result OperateRange(u32 operation_type, u64 offset, u64 size, FsRangeInfo *out_range_info) = 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"
|
#include "fs_shim.h"
|
||||||
|
|
||||||
/* Missing fsp-srv commands. */
|
/* 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) {
|
Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) {
|
||||||
IpcCommand c;
|
IpcCommand c;
|
||||||
ipcInitialize(&c);
|
ipcInitialize(&c);
|
||||||
|
|
|
@ -17,6 +17,7 @@ typedef struct {
|
||||||
} FsRangeInfo;
|
} FsRangeInfo;
|
||||||
|
|
||||||
/* Missing fsp-srv commands. */
|
/* Missing fsp-srv commands. */
|
||||||
|
Result fsOpenBisStorageFwd(Service* s, FsStorage* out, u32 PartitionId);
|
||||||
Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out);
|
Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out);
|
||||||
Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, 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. */
|
/* Represents a RomFS accessed via some IStorage. */
|
||||||
class RomInterfaceStorage : public IROStorage {
|
using RomInterfaceStorage = ROProxyStorage;
|
||||||
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);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
|
@ -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. */
|
/* Add redirection for RomFS to the SD card. */
|
||||||
Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStorageInterface>> out_storage) {
|
Result FsMitmService::OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStorageInterface>> out_storage) {
|
||||||
std::shared_ptr<IStorageInterface> storage = nullptr;
|
std::shared_ptr<IStorageInterface> storage = nullptr;
|
||||||
|
|
|
@ -22,10 +22,30 @@
|
||||||
|
|
||||||
enum FspSrvCmd : u32 {
|
enum FspSrvCmd : u32 {
|
||||||
FspSrvCmd_SetCurrentProcess = 1,
|
FspSrvCmd_SetCurrentProcess = 1,
|
||||||
|
FspSrvCmd_OpenBisStorage = 12,
|
||||||
FspSrvCmd_OpenDataStorageByCurrentProcess = 200,
|
FspSrvCmd_OpenDataStorageByCurrentProcess = 200,
|
||||||
FspSrvCmd_OpenDataStorageByDataId = 202,
|
FspSrvCmd_OpenDataStorageByDataId = 202,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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 {
|
class FsMitmService : public IMitmServiceObject {
|
||||||
private:
|
private:
|
||||||
bool has_initialized = false;
|
bool has_initialized = false;
|
||||||
|
@ -35,9 +55,15 @@ class FsMitmService : public IMitmServiceObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ShouldMitm(u64 pid, u64 tid) {
|
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)) {
|
if (Utils::HasSdDisableMitMFlag(tid)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid)) && Utils::HasOverrideButton(tid);
|
return (tid >= 0x0100000000010000ULL || Utils::HasSdMitMFlag(tid)) && Utils::HasOverrideButton(tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,10 +71,12 @@ class FsMitmService : public IMitmServiceObject {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* Overridden commands. */
|
/* Overridden commands. */
|
||||||
|
Result OpenBisStorage(Out<std::shared_ptr<IStorageInterface>> out, u32 bis_partition_id);
|
||||||
Result OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStorageInterface>> out);
|
Result OpenDataStorageByCurrentProcess(Out<std::shared_ptr<IStorageInterface>> out);
|
||||||
Result OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out, u64 data_id, u8 storage_id);
|
Result OpenDataStorageByDataId(Out<std::shared_ptr<IStorageInterface>> out, u64 data_id, u8 storage_id);
|
||||||
public:
|
public:
|
||||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||||
|
MakeServiceCommandMeta<FspSrvCmd_OpenBisStorage, &FsMitmService::OpenBisStorage>(),
|
||||||
MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByCurrentProcess, &FsMitmService::OpenDataStorageByCurrentProcess>(),
|
MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByCurrentProcess, &FsMitmService::OpenDataStorageByCurrentProcess>(),
|
||||||
MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByDataId, &FsMitmService::OpenDataStorageByDataId>(),
|
MakeServiceCommandMeta<FspSrvCmd_OpenDataStorageByDataId, &FsMitmService::OpenDataStorageByDataId>(),
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue