mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-27 18:30:56 +00:00
Refuse to load truncated ~PSP files.
This commit is contained in:
parent
57a20f02ed
commit
b1b3b7c9d7
@ -37,8 +37,7 @@ enum {
|
||||
R_MIPS_GPREL32
|
||||
};
|
||||
|
||||
enum KnownElfTypes
|
||||
{
|
||||
enum KnownElfTypes {
|
||||
KNOWNELF_PSP = 0,
|
||||
KNOWNELF_DS = 1,
|
||||
KNOWNELF_GBA = 2,
|
||||
@ -46,29 +45,24 @@ enum KnownElfTypes
|
||||
|
||||
typedef int SectionID;
|
||||
|
||||
class ElfReader
|
||||
{
|
||||
class ElfReader {
|
||||
public:
|
||||
ElfReader(const void *ptr) :
|
||||
sectionOffsets(0),
|
||||
sectionAddrs(0),
|
||||
bRelocate(false),
|
||||
entryPoint(0),
|
||||
vaddr(0) {
|
||||
ElfReader(const void *ptr, size_t size) {
|
||||
base = (const char*)ptr;
|
||||
base32 = (const u32 *)ptr;
|
||||
header = (const Elf32_Ehdr*)ptr;
|
||||
segments = (const Elf32_Phdr *)(base + header->e_phoff);
|
||||
sections = (const Elf32_Shdr *)(base + header->e_shoff);
|
||||
size_ = size;
|
||||
}
|
||||
|
||||
~ElfReader() {
|
||||
delete [] sectionOffsets;
|
||||
delete [] sectionAddrs;
|
||||
delete[] sectionOffsets;
|
||||
delete[] sectionAddrs;
|
||||
}
|
||||
|
||||
u32 Read32(int off) {
|
||||
return base32[off>>2];
|
||||
u32 Read32(int off) const {
|
||||
return base32[off >> 2];
|
||||
}
|
||||
|
||||
// Quick accessors
|
||||
@ -100,13 +94,15 @@ public:
|
||||
int GetSectionSize(SectionID section) const {
|
||||
return sections[section].sh_size;
|
||||
}
|
||||
SectionID GetSectionByName(const char *name, int firstSection=0) const; //-1 for not found
|
||||
|
||||
//-1 for not found
|
||||
SectionID GetSectionByName(const char *name, int firstSection = 0) const;
|
||||
|
||||
u32 GetSegmentPaddr(int segment) const {
|
||||
return segments[segment].p_paddr;
|
||||
return segments[segment].p_paddr;
|
||||
}
|
||||
u32 GetSegmentOffset(int segment) const {
|
||||
return segments[segment].p_offset;
|
||||
return segments[segment].p_offset;
|
||||
}
|
||||
u32 GetSegmentVaddr(int segment) const {
|
||||
return segmentVAddr[segment];
|
||||
@ -140,16 +136,17 @@ public:
|
||||
void LoadRelocations2(int rel_seg);
|
||||
|
||||
private:
|
||||
const char *base;
|
||||
const u32 *base32;
|
||||
const Elf32_Ehdr *header;
|
||||
const Elf32_Phdr *segments;
|
||||
const Elf32_Shdr *sections;
|
||||
u32 *sectionOffsets;
|
||||
u32 *sectionAddrs;
|
||||
bool bRelocate;
|
||||
u32 entryPoint;
|
||||
u32 totalSize;
|
||||
u32 vaddr;
|
||||
const char *base = nullptr;
|
||||
const u32 *base32 = nullptr;
|
||||
const Elf32_Ehdr *header = nullptr;
|
||||
const Elf32_Phdr *segments = nullptr;
|
||||
const Elf32_Shdr *sections = nullptr;
|
||||
u32 *sectionOffsets = nullptr;
|
||||
u32 *sectionAddrs = nullptr;
|
||||
bool bRelocate = false;
|
||||
u32 entryPoint = 0;
|
||||
u32 totalSize = 0;
|
||||
u32 vaddr = 0;
|
||||
u32 segmentVAddr[32];
|
||||
size_t size_ = 0;
|
||||
};
|
||||
|
@ -1043,7 +1043,7 @@ static bool KernelImportModuleFuncs(Module *module, u32 *firstImportStubAddr, bo
|
||||
return true;
|
||||
}
|
||||
|
||||
static Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, bool fromTop, std::string *error_string, u32 *magic, u32 &error) {
|
||||
static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAddress, bool fromTop, std::string *error_string, u32 *magic, u32 &error) {
|
||||
Module *module = new Module;
|
||||
kernelObjects.Create(module);
|
||||
loadedModules.insert(module->GetUID());
|
||||
@ -1055,7 +1055,9 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, bool fromT
|
||||
u32_le *magicPtr = (u32_le *) ptr;
|
||||
if (*magicPtr == 0x4543537e) { // "~SCE"
|
||||
INFO_LOG(SCEMODULE, "~SCE module, skipping header");
|
||||
ptr += *(u32_le*)(ptr + 4);
|
||||
u32 headerSize = *(u32_le*)(ptr + 4);
|
||||
ptr += headerSize;
|
||||
elfSize -= headerSize;
|
||||
magicPtr = (u32_le *)ptr;
|
||||
}
|
||||
*magic = *magicPtr;
|
||||
@ -1081,8 +1083,14 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, bool fromT
|
||||
|
||||
const u8 *in = ptr;
|
||||
// Kind of odd.
|
||||
u32 size = std::max(head->elf_size, head->psp_size);
|
||||
newptr = new u8[size];
|
||||
u32 size = head->psp_size;
|
||||
if (size > elfSize) {
|
||||
*error_string = StringFromFormat("ELF/PRX truncated: %d > %d", (int)size, (int)elfSize);
|
||||
module->Cleanup();
|
||||
kernelObjects.Destroy<Module>(module->GetUID());
|
||||
return nullptr;
|
||||
}
|
||||
newptr = new u8[std::max(head->elf_size, head->psp_size)];
|
||||
ptr = newptr;
|
||||
magicPtr = (u32_le *)ptr;
|
||||
int ret = pspDecryptPRX(in, (u8*)ptr, head->psp_size);
|
||||
@ -1147,8 +1155,9 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, bool fromT
|
||||
error = SCE_KERNEL_ERROR_UNSUPPORTED_PRX_TYPE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Open ELF reader
|
||||
ElfReader reader((void*)ptr);
|
||||
ElfReader reader((void*)ptr, elfSize);
|
||||
|
||||
int result = reader.LoadInto(loadAddress, fromTop);
|
||||
if (result != SCE_KERNEL_ERROR_OK) {
|
||||
@ -1439,8 +1448,7 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, bool fromT
|
||||
return module;
|
||||
}
|
||||
|
||||
static Module *__KernelLoadModule(u8 *fileptr, SceKernelLMOption *options, std::string *error_string)
|
||||
{
|
||||
static Module *__KernelLoadModule(u8 *fileptr, size_t fileSize, SceKernelLMOption *options, std::string *error_string) {
|
||||
Module *module = 0;
|
||||
// Check for PBP
|
||||
if (memcmp(fileptr, "\0PBP", 4) == 0) {
|
||||
@ -1455,28 +1463,33 @@ static Module *__KernelLoadModule(u8 *fileptr, SceKernelLMOption *options, std::
|
||||
for (int i = 1; i < numfiles; i++)
|
||||
memcpy(&offsets[i], fileptr + 12 + 4*i, 4);
|
||||
|
||||
if (offsets[6] > fileSize) {
|
||||
// File is too small to fully contain the ELF! Must have been truncated.
|
||||
*error_string = "ELF file truncated - can't load";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
u32 magic = 0;
|
||||
u8 *temp = 0;
|
||||
u8 *temp = nullptr;
|
||||
size_t elfSize = offsets[6] - offsets[5];
|
||||
if (offsets[5] & 3) {
|
||||
// Our loader does NOT like to load from an unaligned address on ARM!
|
||||
size_t size = offsets[6] - offsets[5];
|
||||
temp = new u8[size];
|
||||
memcpy(temp, fileptr + offsets[5], size);
|
||||
// Our loader does NOT like to load from an unaligned address on ARM! Copy to a new block.
|
||||
temp = new u8[elfSize];
|
||||
|
||||
memcpy(temp, fileptr + offsets[5], elfSize);
|
||||
INFO_LOG(LOADER, "PBP: ELF unaligned (%d: %d), aligning!", offsets[5], offsets[5] & 3);
|
||||
}
|
||||
|
||||
u32 error;
|
||||
module = __KernelLoadELFFromPtr(temp ? temp : fileptr + offsets[5], PSP_GetDefaultLoadAddress(), false, error_string, &magic, error);
|
||||
module = __KernelLoadELFFromPtr(temp ? temp : fileptr + offsets[5], elfSize, PSP_GetDefaultLoadAddress(), false, error_string, &magic, error);
|
||||
|
||||
if (temp) {
|
||||
delete [] temp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
u32 error;
|
||||
u32 magic = 0;
|
||||
module = __KernelLoadELFFromPtr(fileptr, PSP_GetDefaultLoadAddress(), false, error_string, &magic, error);
|
||||
module = __KernelLoadELFFromPtr(fileptr, fileSize, PSP_GetDefaultLoadAddress(), false, error_string, &magic, error);
|
||||
}
|
||||
|
||||
return module;
|
||||
@ -1582,7 +1595,7 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str
|
||||
|
||||
pspFileSystem.ReadFile(handle, temp, (size_t)info.size);
|
||||
|
||||
Module *module = __KernelLoadModule(temp, 0, error_string);
|
||||
Module *module = __KernelLoadModule(temp, (size_t)info.size, 0, error_string);
|
||||
|
||||
if (!module || module->isFake) {
|
||||
if (module) {
|
||||
@ -1797,7 +1810,7 @@ u32 sceKernelLoadModule(const char *name, u32 flags, u32 optionAddr) {
|
||||
u32 magic;
|
||||
u32 error;
|
||||
std::string error_string;
|
||||
module = __KernelLoadELFFromPtr(temp, 0, lmoption ? lmoption->position == 1 : false, &error_string, &magic, error);
|
||||
module = __KernelLoadELFFromPtr(temp, (size_t)size, 0, lmoption ? lmoption->position == 1 : false, &error_string, &magic, error);
|
||||
delete [] temp;
|
||||
pspFileSystem.CloseFile(handle);
|
||||
|
||||
@ -2243,7 +2256,7 @@ static u32 sceKernelLoadModuleByID(u32 id, u32 flags, u32 lmoptionPtr)
|
||||
u8 *temp = new u8[size - pos];
|
||||
pspFileSystem.ReadFile(handle, temp, size - pos);
|
||||
u32 magic;
|
||||
module = __KernelLoadELFFromPtr(temp, 0, lmoption ? lmoption->position == 1 : false, &error_string, &magic, error);
|
||||
module = __KernelLoadELFFromPtr(temp, size - pos, 0, lmoption ? lmoption->position == 1 : false, &error_string, &magic, error);
|
||||
delete [] temp;
|
||||
|
||||
if (!module) {
|
||||
@ -2300,7 +2313,7 @@ static SceUID sceKernelLoadModuleBufferUsbWlan(u32 size, u32 bufPtr, u32 flags,
|
||||
Module *module = 0;
|
||||
u32 magic;
|
||||
u32 error;
|
||||
module = __KernelLoadELFFromPtr(Memory::GetPointer(bufPtr), 0, lmoption ? lmoption->position == 1 : false, &error_string, &magic, error);
|
||||
module = __KernelLoadELFFromPtr(Memory::GetPointer(bufPtr), size, 0, lmoption ? lmoption->position == 1 : false, &error_string, &magic, error);
|
||||
|
||||
if (!module) {
|
||||
// Some games try to load strange stuff as PARAM.SFO as modules and expect it to fail.
|
||||
|
Loading…
Reference in New Issue
Block a user