TestSharedMappingCommit.cpp (4310B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 6 7 #include <cstdint> 8 #include <cstdio> 9 #include <windows.h> 10 11 // Tests that when there are multiple views to a unique mapping, committing 12 // memory pages for one of the views actually commits them for all views. We 13 // rely on this behavior in `mozglue/interceptor/MMPolicies.h` and in 14 // `security/sandbox/chromium/sandbox/win/src/interception.cc`. 15 bool TestSharedMappingCommit() { 16 constexpr size_t kMappingSize = 64 * 1024; 17 constexpr size_t kCommitOffset = 32 * 1024; 18 constexpr size_t kCommitSize = 4 * 1024; 19 20 HANDLE mapping = ::CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, 21 PAGE_EXECUTE_READWRITE | SEC_RESERVE, 0, 22 kMappingSize, nullptr); 23 if (!mapping) { 24 printf( 25 "TEST-FAIL | SharedMappingCommit | Failed to create a pagefile-backed " 26 "mapping\n"); 27 return false; 28 } 29 30 void* rwView = 31 ::MapViewOfFile(mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); 32 if (!rwView) { 33 printf( 34 "TEST-FAIL | SharedMappingCommit | Failed to get a read/write view\n"); 35 return false; 36 } 37 38 void* rxView = 39 ::MapViewOfFile(mapping, FILE_MAP_READ | FILE_MAP_EXECUTE, 0, 0, 0); 40 if (!rxView) { 41 printf( 42 "TEST-FAIL | SharedMappingCommit | Failed to get a read/execute " 43 "view\n"); 44 return false; 45 } 46 47 auto* rwCommitAddress = 48 static_cast<void*>(static_cast<uint8_t*>(rwView) + kCommitOffset); 49 auto* rxCommitAddress = 50 static_cast<void*>(static_cast<uint8_t*>(rxView) + kCommitOffset); 51 52 { 53 MEMORY_BASIC_INFORMATION info{}; 54 if (::VirtualQuery(rxCommitAddress, &info, sizeof(info)) != sizeof(info)) { 55 printf( 56 "TEST-FAIL | SharedMappingCommit | Failed to query basic information " 57 "about the read/execute memory pages\n"); 58 return false; 59 } 60 if (info.State != MEM_RESERVE) { 61 printf( 62 "TEST-FAIL | SharedMappingCommit | Unexpected initial state for the " 63 "read/execute memory pages: %lu\n", 64 info.State); 65 return false; 66 } 67 } 68 69 rwCommitAddress = ::VirtualAlloc(static_cast<void*>(rwCommitAddress), 70 kCommitSize, MEM_COMMIT, PAGE_READWRITE); 71 if (!rwCommitAddress) { 72 printf( 73 "TEST-FAIL | SharedMappingCommit | Failed to commit read/write " 74 "memory pages\n"); 75 return false; 76 } 77 78 { 79 MEMORY_BASIC_INFORMATION info{}; 80 if (::VirtualQuery(rxCommitAddress, &info, sizeof(info)) != sizeof(info)) { 81 printf( 82 "TEST-FAIL | SharedMappingCommit | Failed to query basic information " 83 "about the read/execute memory pages\n"); 84 return false; 85 } 86 if (info.State != MEM_COMMIT) { 87 printf( 88 "TEST-FAIL | SharedMappingCommit | Read/write commit hasn't changed " 89 "the state of the read/execute memory pages: %lu\n", 90 info.State); 91 return false; 92 } 93 if (info.Protect != PAGE_EXECUTE_READ) { 94 printf( 95 "TEST-FAIL | SharedMappingCommit | Unexpected protection for the " 96 "read/execute memory pages: %lu\n", 97 info.Protect); 98 return false; 99 } 100 } 101 102 constexpr uint32_t kMagic = 0xdeadbeef; 103 104 uint32_t* rwMagicAddr = static_cast<uint32_t*>(rwCommitAddress); 105 *rwMagicAddr = kMagic; 106 107 const uint32_t* rxMagicAddr = static_cast<const uint32_t*>(rxCommitAddress); 108 if (*rxMagicAddr != kMagic) { 109 printf( 110 "TEST-FAIL | SharedMappingCommit | Read a different value through the " 111 "read/execute view than was written through the read/write view\n"); 112 return false; 113 } 114 115 printf( 116 "TEST-PASS | SharedMappingCommit | Committing memory pages through the " 117 "read/write view also commited the corresponding pages in the " 118 "read/execute view\n"); 119 return true; 120 } 121 122 int wmain(int argc, wchar_t* argv[]) { 123 if (!TestSharedMappingCommit()) { 124 return 1; 125 } 126 127 printf("TEST-PASS | SharedMappingCommit | All tests ran successfully\n"); 128 return 0; 129 }