From 62f7a06192b2abce498f09741e5b0704d4fae473 Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 16 Oct 2016 02:47:53 +0200 Subject: [PATCH] Add safety checks for loaded FIRM modules --- source/draw.c | 28 ++++++++++++++++++---------- source/firm.c | 33 ++++++++++++++++++++++++--------- source/pin.c | 9 ++++++--- 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/source/draw.c b/source/draw.c index dd37e1c..df0c0ee 100644 --- a/source/draw.c +++ b/source/draw.c @@ -38,23 +38,31 @@ bool loadSplash(void) *bottomSplashFile = "splashbottom.bin"; bool isTopSplashValid = getFileSize(topSplashFile) == SCREEN_TOP_FBSIZE, - isBottomSplashValid = getFileSize(bottomSplashFile) == SCREEN_BOTTOM_FBSIZE; + isBottomSplashValid = getFileSize(bottomSplashFile) == SCREEN_BOTTOM_FBSIZE, + ret; //Don't delay boot nor init the screens if no splash images or invalid splash images are on the SD - if(!isTopSplashValid && !isBottomSplashValid) - return false; + if(!isTopSplashValid && !isBottomSplashValid) ret = false; + else + { + initScreens(); + clearScreens(true, true, true); - initScreens(); - clearScreens(true, true, true); + if(isTopSplashValid) isTopSplashValid = fileRead(fbs[1].top_left, topSplashFile, SCREEN_TOP_FBSIZE) == SCREEN_TOP_FBSIZE; + if(isBottomSplashValid) isBottomSplashValid = fileRead(fbs[1].bottom, bottomSplashFile, SCREEN_BOTTOM_FBSIZE) == SCREEN_BOTTOM_FBSIZE; - if(isTopSplashValid) fileRead(fbs[1].top_left, topSplashFile, SCREEN_TOP_FBSIZE); - if(isBottomSplashValid) fileRead(fbs[1].bottom, bottomSplashFile, SCREEN_BOTTOM_FBSIZE); + if(!isTopSplashValid && !isBottomSplashValid) ret = false; + else + { + swapFramebuffers(true); - swapFramebuffers(true); + chrono(3); - chrono(3); + ret = true; + } + } - return true; + return ret; } void drawCharacter(char character, bool isTopScreen, u32 posX, u32 posY, u32 color) diff --git a/source/firm.c b/source/firm.c index a21b8e1..8653339 100755 --- a/source/firm.c +++ b/source/firm.c @@ -285,18 +285,20 @@ u32 patch1x2xNativeAndSafeFirm(u32 devMode) static inline void copySection0AndInjectSystemModules(FirmwareType firmType, bool loadFromStorage) { - u32 srcModuleSize, + u32 maxModuleSize = firmType == NATIVE_FIRM ? 0x80000 : 0x600000, + srcModuleSize, dstModuleSize; for(u8 *src = (u8 *)firm + firm->section[0].offset, *srcEnd = src + firm->section[0].size, *dst = firm->section[0].address; - src < srcEnd; src += srcModuleSize, dst += dstModuleSize) + src < srcEnd; src += srcModuleSize, dst += dstModuleSize, maxModuleSize -= dstModuleSize) { srcModuleSize = ((Cxi *)src)->ncch.contentSize * 0x200; const char *moduleName = ((Cxi *)src)->exHeader.systemControlInfo.appTitle; - u32 fileSize; + bool loadedModule; - if(loadFromStorage) + if(!loadFromStorage) loadedModule = false; + else { char fileName[24] = "sysmodules/"; const char *ext = ".cxi"; @@ -305,12 +307,23 @@ static inline void copySection0AndInjectSystemModules(FirmwareType firmType, boo concatenateStrings(fileName, moduleName); concatenateStrings(fileName, ext); - fileSize = fileRead(dst, fileName, 2 * srcModuleSize); - } - else fileSize = 0; + dstModuleSize = getFileSize(fileName); - if(fileSize > 0) dstModuleSize = fileSize; - else + if(dstModuleSize == 0) loadedModule = false; + else + { + if(dstModuleSize <= sizeof(Cxi) + 0x200 || + dstModuleSize > maxModuleSize || + fileRead(dst, fileName, dstModuleSize) != dstModuleSize || + memcmp(((Cxi *)dst)->ncch.magic, "NCCH", 4) != 0 || + memcmp(moduleName, ((Cxi *)dst)->exHeader.systemControlInfo.appTitle, sizeof(((Cxi *)dst)->exHeader.systemControlInfo.appTitle)) != 0) + error("An external FIRM module is invalid."); + + loadedModule = true; + } + } + + if(!loadedModule) { const u8 *module; @@ -325,6 +338,8 @@ static inline void copySection0AndInjectSystemModules(FirmwareType firmType, boo dstModuleSize = srcModuleSize; } + if(dstModuleSize > maxModuleSize) error("The FIRM modules section is full."); + memcpy(dst, module, dstModuleSize); } } diff --git a/source/pin.c b/source/pin.c index 129bfb3..3f181f6 100644 --- a/source/pin.c +++ b/source/pin.c @@ -139,9 +139,12 @@ bool verifyPin(u32 pinMode) if(messageSize > 0 && messageSize <= 800) { char message[messageSize + 1]; - fileRead(message, messageFile, messageSize); - message[messageSize] = 0; - drawString(message, false, 10, 10, COLOR_WHITE); + + if(fileRead(message, messageFile, messageSize) == messageSize) + { + message[messageSize] = 0; + drawString(message, false, 10, 10, COLOR_WHITE); + } } while(!unlock)