Implement guard pages (#406)

Hey, looking for feedback on my guard page implementation. 

I wasn't sure on how to structure the additional windows specific memory
flags, since the emulation backends won't like additional guard flag. I
opted to create a new `memory_permission_ext` enum to hold the guard
flag, and a `nt_memory_permission` struct to wrap the "common" memory
permission flags, with the new extended flags. This struct implicitly
coerces to the original `memory_permission` to reduce the amount of
changes for the PR.

This however meant that I changed signatures of `map_memory` and
`apply_memory_protection` in `memory_interface` to accommodate this new
structure, and was an afterthought.

The `map_nt_to_emulator_protection` function might also need some
attention now, too. For future reference, windows uses
[MiMakeProtectionMask](https://doxygen.reactos.org/d1/d9a/marea_8c.html#adfb66408771a4df77c1056cc2a99ef21)
in ntoskrnl to map `PAGE_*` flags to [MM PTE
constants](https://reactos.org/wiki/Techwiki:Memory_management_in_the_Windows_XP_kernel).

The test added to the `test-sample` binary seems to be passing.

Fixes #21
This commit is contained in:
Maurice Heumann
2025-07-17 17:41:06 +02:00
committed by GitHub
13 changed files with 359 additions and 34 deletions

View File

@@ -11,6 +11,7 @@
#include "apiset/apiset.hpp"
#include "network/static_socket_factory.hpp"
#include "memory_permission_ext.hpp"
constexpr auto MAX_INSTRUCTIONS_PER_TIME_SLICE = 0x20000;
@@ -501,8 +502,20 @@ void windows_emulator::setup_hooks()
this->emu().hook_memory_violation([&](const uint64_t address, const size_t size, const memory_operation operation,
const memory_violation_type type) {
this->callbacks.on_memory_violate(address, size, operation, type);
dispatch_access_violation(this->emu(), this->process, address, operation);
auto region = this->memory.get_region_info(address);
if (region.permissions.is_guarded())
{
// Unset the GUARD_PAGE flag and dispatch a STATUS_GUARD_PAGE_VIOLATION
this->memory.protect_memory(region.allocation_base, region.length,
region.permissions & ~memory_permission_ext::guard);
dispatch_guard_page_violation(this->emu(), this->process, address, operation);
}
else
{
this->callbacks.on_memory_violate(address, size, operation, type);
dispatch_access_violation(this->emu(), this->process, address, operation);
}
return memory_violation_continuation::resume;
});