mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-19 09:19:05 +02:00
Write-protect the dispatcher on all platforms.
This commit is contained in:
1 parent
5005e83254
commit
323eb72b7c
6 files changed
+45
-19
No files matched your search
+20
-5
@@ -291,6 +291,10 @@ bool PlatformIsWXExclusive() {
|
||||
}
|
||||
|
||||
void ProtectMemoryPages(void* ptr, size_t size, uint32_t memProtFlags) {
|
||||
if (PlatformIsWXExclusive()) {
|
||||
if ((memProtFlags & (MEM_PROT_WRITE | MEM_PROT_EXEC)) == (MEM_PROT_WRITE | MEM_PROT_EXEC))
|
||||
PanicAlert("Bad memory protect : W^X is in effect, can't both write and exec");
|
||||
}
|
||||
#ifdef _WIN32
|
||||
uint32_t protect = ConvertProtFlagsWin32(memProtFlags);
|
||||
DWORD oldValue;
|
||||
@@ -300,10 +304,21 @@ void ProtectMemoryPages(void* ptr, size_t size, uint32_t memProtFlags) {
|
||||
// Do nothing
|
||||
#else
|
||||
uint32_t protect = ConvertProtFlagsUnix(memProtFlags);
|
||||
if (PlatformIsWXExclusive()) {
|
||||
if ((flags & (MEM_PROT_WRITE | MEM_PROT_EXEC)) == (MEM_PROT_WRITE | MEM_PROT_EXEC))
|
||||
PanicAlert("Bad memory protect : W^X is in effect, can't both write and exec");
|
||||
}
|
||||
mprotect(ptr, size, protect);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Hardcoded in the header. This is a way to check it dynamically in case it ever becomes necessary.
|
||||
/*
|
||||
#ifdef _WIN32
|
||||
|
||||
// 4k on most archs, 8k on Itanium (but who cares).
|
||||
// Should not be confused with the allocation granularity which is 65k and is how precise
|
||||
// VirtualAlloc allocations can be located in memory. We don't really care about that much though.
|
||||
int GetMemoryProtectPageSize() {
|
||||
if (sys_info.dwPageSize == 0)
|
||||
GetSystemInfo(&sys_info);
|
||||
return sys_info.dwPageSize;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
+7
-8
@@ -29,18 +29,21 @@ using std::size_t;
|
||||
// Returns true if we need to avoid setting both writable and executable at the same time (W^X)
|
||||
bool PlatformIsWXExclusive();
|
||||
|
||||
|
||||
#define MEM_PROT_READ 1
|
||||
#define MEM_PROT_WRITE 2
|
||||
#define MEM_PROT_EXEC 4
|
||||
|
||||
// Note that some platforms go through special contortions to allocate executable memory. So for memory
|
||||
// that's intended for execution, allocate it first using AllocateExecutableMemory, then modify protection as desired.
|
||||
// AllocateMemoryPages is simpler and more generic.
|
||||
// AllocateMemoryPages is simpler and more generic. Note that on W^X platforms, this will return executable but not writable
|
||||
// memory!
|
||||
void* AllocateExecutableMemory(size_t size);
|
||||
void* AllocateMemoryPages(size_t size, uint32_t memProtFlags);
|
||||
// Note that on platforms returning PlatformIsWXExclusive, you cannot set a page to be both readable and writable at the same time.
|
||||
void ProtectMemoryPages(void* ptr, size_t size, uint32_t memProtFlags);
|
||||
inline void ProtectMemoryPages(const void *start, const void *end, uint32_t memProtFlags) {
|
||||
ProtectMemoryPages((void *)start, (const uint8_t *)end - (const uint8_t *)start, memProtFlags);
|
||||
}
|
||||
void FreeMemoryPages(void* ptr, size_t size);
|
||||
|
||||
// Regular aligned memory. Don't try to apply memory protection willy-nilly to memory allocated this way as in-page alignment is unknown (though could be checked).
|
||||
@@ -52,12 +55,8 @@ void ResetExecutableMemory(void* ptr);
|
||||
#endif
|
||||
|
||||
inline int GetMemoryProtectPageSize() {
|
||||
#ifdef _WIN32
|
||||
// For memory protection purposes, Windows is still stuck at 64k except in WSL (linux on windows).
|
||||
return 65536;
|
||||
#else
|
||||
return PAGE_SIZE;
|
||||
#endif
|
||||
// This is 4096 on all platforms we care about. 8k on Itanium but meh.
|
||||
return 4096;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -135,9 +135,11 @@ const u8 *XEmitter::AlignCode16()
|
||||
|
||||
const u8 *XEmitter::AlignCodePage()
|
||||
{
|
||||
int c = int((u64)code & 4095);
|
||||
// Memory protection pages matter.
|
||||
int page_size = GetMemoryProtectPageSize();
|
||||
int c = int((u64)code & (page_size - 1));
|
||||
if (c)
|
||||
ReserveCodeSpace(4096-c);
|
||||
ReserveCodeSpace(page_size - c);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ namespace MIPSComp {
|
||||
using namespace ArmJitConstants;
|
||||
|
||||
void ArmJit::GenerateFixedCode() {
|
||||
const u8 *start = GetCodePtr();
|
||||
const u8 *start = AlignCodePage();
|
||||
|
||||
// LR == SCRATCHREG2 on ARM32 so it needs to be pushed.
|
||||
restoreRoundingMode = AlignCode16(); {
|
||||
@@ -279,6 +279,10 @@ void ArmJit::GenerateFixedCode() {
|
||||
// Don't forget to zap the instruction cache!
|
||||
FlushLitPool();
|
||||
FlushIcache();
|
||||
|
||||
// Freeze the dispatcher code
|
||||
const void *end = AlignCodePage();
|
||||
ProtectMemoryPages(start, end, MEM_PROT_READ | MEM_PROT_EXEC);
|
||||
}
|
||||
|
||||
} // namespace MIPSComp
|
||||
@@ -94,7 +94,7 @@ namespace MIPSComp {
|
||||
using namespace Arm64JitConstants;
|
||||
|
||||
void Arm64Jit::GenerateFixedCode(const JitOptions &jo) {
|
||||
const u8 *start = AlignCode16();
|
||||
const u8 *start = AlignCodePage();
|
||||
if (jo.useStaticAlloc) {
|
||||
saveStaticRegisters = AlignCode16();
|
||||
STR(INDEX_UNSIGNED, DOWNCOUNTREG, CTXREG, offsetof(MIPSState, downcount));
|
||||
@@ -316,6 +316,9 @@ void Arm64Jit::GenerateFixedCode(const JitOptions &jo) {
|
||||
|
||||
// Don't forget to zap the instruction cache! This must stay at the end of this function.
|
||||
FlushIcache();
|
||||
// Freeze the dispatcher code
|
||||
const void *end = AlignCodePage();
|
||||
ProtectMemoryPages(start, end, MEM_PROT_READ | MEM_PROT_EXEC);
|
||||
}
|
||||
|
||||
} // namespace MIPSComp
|
||||
@@ -63,7 +63,7 @@ void ImHere() {
|
||||
}
|
||||
|
||||
void Jit::GenerateFixedCode(JitOptions &jo) {
|
||||
const u8 *start = AlignCode16();
|
||||
const u8 *start = AlignCodePage();
|
||||
|
||||
restoreRoundingMode = AlignCode16(); {
|
||||
STMXCSR(M(&mips_->temp));
|
||||
@@ -217,7 +217,10 @@ void Jit::GenerateFixedCode(JitOptions &jo) {
|
||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||
RET();
|
||||
|
||||
endOfPregeneratedCode = GetCodePtr();
|
||||
endOfPregeneratedCode = AlignCodePage();
|
||||
|
||||
// Freeze the pre-generated code.
|
||||
ProtectMemoryPages(start, endOfPregeneratedCode, MEM_PROT_READ | MEM_PROT_EXEC);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in new issue
Block a user