mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-29 12:15:39 +00:00
feat(libkernel): guest memory protection and VirtualQuery on macOS hosts
- mprotect: the guest rounds a range to its 16 KiB pages. A Mach-O image
is loaded at a multiple of the host page size only (4 KiB under
Rosetta), so the pages are counted from where the ELF address 0 of the
image holding the range was loaded, and a rounded edge smaller than a
guest page that lies in the gap between two segments, where no host page
exists, is left out. The write watch is told the new protection.
- sceKernelVirtualQuery reads the region with mach_vm_region.
- sceKernelMunlockall unlocks the ranges libkernel locked, one by one:
macOS has no munlockall, which fails there with ENOSYS and would
overwrite errno.
- The stack protect test reads page protections with mach_vm_region.
This is mugurc's f66a4df741 from his macOS series, without the mlock
check that #10889 adds.
Co-authored-by: mugurc <[email protected]>
This commit is contained in:
1 parent
81267b2204
commit
190ed6c8fb
6 files changed
+99
-6
No files matched your search
@@ -13,6 +13,10 @@
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#elif defined(__APPLE__)
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_vm.h>
|
||||
#include <sys/mman.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
@@ -39,6 +43,16 @@ static PageState QueryPage(std::uintptr_t address) {
|
||||
Require(VirtualQuery(reinterpret_cast<const void*>(address), &memory, sizeof(memory)) == sizeof(memory));
|
||||
const bool mapped = memory.State == MEM_COMMIT;
|
||||
return {mapped, mapped && (memory.Protect & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE)) != 0, (static_cast<std::uint64_t>(memory.State) << 32) | memory.Protect};
|
||||
#elif defined(__APPLE__)
|
||||
mach_vm_address_t region = address;
|
||||
mach_vm_size_t size = 0;
|
||||
vm_region_basic_info_data_64_t info{};
|
||||
mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64;
|
||||
mach_port_t object = MACH_PORT_NULL;
|
||||
if (mach_vm_region(mach_task_self(), ®ion, &size, VM_REGION_BASIC_INFO_64, reinterpret_cast<vm_region_info_t>(&info), &count, &object) != KERN_SUCCESS || region > address) return {false, false, 0};
|
||||
const bool readable = (info.protection & VM_PROT_READ) != 0;
|
||||
const bool writable = (info.protection & VM_PROT_WRITE) != 0;
|
||||
return {true, readable && writable, 1ull | (readable ? 2ull : 0) | (writable ? 4ull : 0) | ((info.protection & VM_PROT_EXECUTE) != 0 ? 8ull : 0)};
|
||||
#else
|
||||
std::FILE* maps = std::fopen("/proc/self/maps", "r");
|
||||
Require(maps != nullptr);
|
||||
|
||||
Reference in new issue
Block a user