From a07e37121dafd1c2027e7bda1db03bba1d059927 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 15 Nov 2018 18:25:11 -0800 Subject: [PATCH] fs.mitm: loosen boot0 write restrictions, protect keyblobs. --- .../fs_mitm/source/fsmitm_boot0storage.cpp | 50 +++++++++++++++---- .../fs_mitm/source/fsmitm_boot0storage.hpp | 5 +- .../fs_mitm/source/fsmitm_service.hpp | 4 +- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp b/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp index e2b25ad40..1554496bd 100644 --- a/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_boot0storage.cpp @@ -23,10 +23,6 @@ static HosMutex g_boot0_mutex; static u8 g_boot0_bct_buffer[Boot0Storage::BctEndOffset]; -bool Boot0Storage::AllowWrites() { - return this->title_id < 0x0100000000001000ULL; -} - bool Boot0Storage::CanModifyBctPubks() { return this->title_id != 0x010000000000001FULL; } @@ -40,18 +36,52 @@ Result Boot0Storage::Read(void *_buffer, size_t size, u64 offset) { Result Boot0Storage::Write(void *_buffer, size_t size, u64 offset) { std::scoped_lock lk{g_boot0_mutex}; - if (!AllowWrites()) { - return 0x313802; + Result rc = 0; + u8 *buffer = static_cast(_buffer); + + /* Protect the keyblob region from writes. */ + if (offset <= EksStart) { + if (offset + size < EksStart) { + /* Fall through, no need to do anything here. */ + } else { + if (offset + size < EksEnd) { + /* Adjust size to avoid writing end of data. */ + size = EksStart - offset; + } else { + /* Perform portion of write falling past end of keyblobs. */ + const u64 diff = EksEnd - offset; + if (R_FAILED((rc = Base::Write(buffer + diff, size - diff, EksEnd)))) { + return rc; + } + /* Adjust size to avoid writing end of data. */ + size = EksStart - offset; + } + } + } else { + if (offset < EksEnd) { + if (offset + size < EksEnd) { + /* Ignore writes falling strictly within the region. */ + return 0; + } else { + /* Only write past the end of the keyblob region. */ + buffer = buffer + (EksEnd - offset); + size -= (EksEnd - offset); + offset = EksEnd; + } + } else { + /* Fall through, no need to do anything here. */ + } + } + + if (size == 0) { + return 0; } /* We care about protecting autorcm from NS. */ if (CanModifyBctPubks() || offset >= BctEndOffset || (offset + BctSize >= BctEndOffset && offset % BctSize >= BctPubkEnd)) { - return Base::Write(_buffer, size, offset); + return Base::Write(buffer, size, offset); } - Result rc = 0; - u8 *buffer = static_cast(_buffer); - /* First, let's deal with the data past the end. */ if (offset + size >= BctEndOffset) { const u64 diff = BctEndOffset - offset; diff --git a/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp b/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp index cf53948f4..b86791ff8 100644 --- a/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_boot0storage.hpp @@ -142,10 +142,13 @@ class Boot0Storage : public SectoredProxyStorage<0x200> { static constexpr u64 BctPubkStart = 0x210; static constexpr u64 BctPubkSize = 0x100; static constexpr u64 BctPubkEnd = BctPubkStart + BctPubkSize; + + static constexpr u64 EksStart = 0x180000; + static constexpr u64 EksSize = 0x4000; + static constexpr u64 EksEnd = EksStart + EksSize; private: u64 title_id; private: - bool AllowWrites(); bool CanModifyBctPubks(); public: Boot0Storage(FsStorage *s, u64 t) : Base(s), title_id(t) { } diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 777782b46..fd69bc85a 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -41,8 +41,8 @@ class FsMitmService : public IMitmServiceObject { } static bool ShouldMitm(u64 pid, u64 tid) { - /* fs.mitm should always mitm everything. */ - return true; + /* fs.mitm should always mitm everything that's not a kip. */ + return pid >= 0x50; } static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx);