From c30ac7c904ca9cd678a064b73c0b66b0b333ba99 Mon Sep 17 00:00:00 2001 From: nmzik Date: Wed, 7 Oct 2026 22:27:35 +0400 Subject: [PATCH] memory: avoid redundant Windows view protection --- src/kernel/memory.cpp | 30 ++++++++++++++++++++++++++ src/kernel/memoryAddressSpace.inc | 2 +- tests/VirtualMemoryAllocationTests.cpp | 18 ++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/kernel/memory.cpp b/src/kernel/memory.cpp index 1137a4cc9..b01612cb6 100644 --- a/src/kernel/memory.cpp +++ b/src/kernel/memory.cpp @@ -3621,6 +3621,36 @@ uint64_t TestGuestBackingSize() { return g_guest_address_space->GetBackingSize(); } +#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS +bool TestWindowsBackingViewModes() { + constexpr uint64_t size = 0x10000; + GuestBackingStore backing(size); + void* placeholder = VirtualAlloc2(GetCurrentProcess(), nullptr, size, + MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, + nullptr, 0); + if (placeholder == nullptr) { + return false; + } + const auto address = reinterpret_cast(placeholder); + bool valid = true; + for (auto [mode, protection]: std::array { + std::pair {VirtualMemory::Mode::NoAccess, DWORD {PAGE_NOACCESS}}, + std::pair {VirtualMemory::Mode::Read, DWORD {PAGE_READONLY}}, + std::pair {VirtualMemory::Mode::ReadWrite, DWORD {PAGE_READWRITE}}, + std::pair {VirtualMemory::Mode::ExecuteReadWrite, DWORD {PAGE_EXECUTE_READWRITE}}}) { + if (!backing.MapFixed(address, size, 0, mode)) { + valid = false; + break; + } + MEMORY_BASIC_INFORMATION info {}; + valid = VirtualQuery(placeholder, &info, sizeof(info)) != 0 && + info.Type == MEM_MAPPED && info.Protect == protection && valid; + EXIT_IF(!backing.Unmap(address, size)); + } + return VirtualFree(placeholder, 0, MEM_RELEASE) != 0 && valid; +} +#endif + bool TestGuestFreeRangeBounds() { return GuestFreeRangeContains(0x10000, 0x20000, 0x18000, 0x4000) && !GuestFreeRangeContains(0x10000, 0x20000, 0x40000, 0x4000) && diff --git a/src/kernel/memoryAddressSpace.inc b/src/kernel/memoryAddressSpace.inc index 40f4e5385..346c8b1ac 100644 --- a/src/kernel/memoryAddressSpace.inc +++ b/src/kernel/memoryAddressSpace.inc @@ -597,7 +597,7 @@ private: return nullptr; } - if (!ApplyProtection(ptr, size, mode)) { + if (mode == VirtualMemory::Mode::NoAccess && !ApplyProtection(ptr, size, mode)) { UnmapViewOfFile2(GetCurrentProcess(), ptr, MEM_PRESERVE_PLACEHOLDER); SetFailure(failure_reason, FailureReason::ProtectFailed); return nullptr; diff --git a/tests/VirtualMemoryAllocationTests.cpp b/tests/VirtualMemoryAllocationTests.cpp index 14c60a9c9..74d78ccab 100644 --- a/tests/VirtualMemoryAllocationTests.cpp +++ b/tests/VirtualMemoryAllocationTests.cpp @@ -60,6 +60,12 @@ #endif #endif +#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS +namespace Libs::LibKernel::Memory { +bool TestWindowsBackingViewModes(); +} +#endif + namespace Libs::Fiber { struct FiberObject; struct FiberOptParam; @@ -1355,6 +1361,15 @@ void TestPartialUnmapPreservesHostPermissions() { } #endif +#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS +void TestWindowsBackingViewPermissions() { + const char* test = "WindowsBackingViewPermissions"; + Check(test, Libs::LibKernel::Memory::TestWindowsBackingViewModes(), + "backing view permissions differ from the requested mode"); + std::printf("[host] %-48s ok\n", test); +} +#endif + void TestDirectMapValidationBeforeOwnerMutation() { const char* test = "DirectMapValidationBeforeOwnerMutation"; int64_t invalid = -1; @@ -4248,6 +4263,9 @@ int main(int argc, char** argv) { RunTest(TestDirectPartialProtectUnmapPreservesNeighbors); #if defined(__linux__) RunTest(TestPartialUnmapPreservesHostPermissions); +#endif +#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS + RunTest(TestWindowsBackingViewPermissions); #endif RunTest(TestDirectMapValidationBeforeOwnerMutation); RunTest(TestDirectReleaseRollbackRestoresOwnerMapping);