Reactos
at master 657 lines 34 kB view raw
1/* 2* PROJECT: ReactOS kernel-mode tests 3* LICENSE: GPLv2+ - See COPYING in the top level directory 4* PURPOSE: Kernel-Mode Test Suite ZwMapViewOfSection 5* PROGRAMMER: Nikolay Borisov <nib9@aber.ac.uk> 6*/ 7 8#include <kmt_test.h> 9 10#define IGNORE -99 11#define NEW_CONTENT "NewContent" 12#define NEW_CONTENT_LEN sizeof(NEW_CONTENT) 13#define IsInvalidParamStatus(Status) \ 14 (Status == STATUS_INVALID_PARAMETER || Status == STATUS_INVALID_PARAMETER_MIX || \ 15 (Status >= STATUS_INVALID_PARAMETER_1 && Status <= STATUS_INVALID_PARAMETER_12)) 16#define ok_invalid_parameter(Status) ok(IsInvalidParamStatus(Status), "Invalid status code (0x%X)\n", Status) 17 18static UNICODE_STRING FileReadOnlyPath = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\ntdll.dll"); 19static UNICODE_STRING NtosImgPath = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\ntoskrnl.exe"); 20static UNICODE_STRING WritableFilePath = RTL_CONSTANT_STRING(L"\\SystemRoot\\kmtest-MmSection.txt"); 21static UNICODE_STRING SharedSectionName = RTL_CONSTANT_STRING(L"\\BaseNamedObjects\\kmtest-SharedSection"); 22extern const char TestString[]; 23extern const ULONG TestStringSize; 24static OBJECT_ATTRIBUTES NtdllObject; 25static OBJECT_ATTRIBUTES KmtestFileObject; 26static OBJECT_ATTRIBUTES NtoskrnlFileObject; 27 28#define TestMapView(SectionHandle, ProcessHandle, BaseAddress2, ZeroBits, CommitSize, SectionOffset, ViewSize2, InheritDisposition, AllocationType, Win32Protect, MapStatus, UnmapStatus) do \ 29 { \ 30 Status = ZwMapViewOfSection(SectionHandle, ProcessHandle, BaseAddress2, ZeroBits, CommitSize, SectionOffset, ViewSize2, InheritDisposition, AllocationType, Win32Protect); \ 31 if (GetNTVersion() >= _WIN32_WINNT_WIN10 && IsInvalidParamStatus(MapStatus)) \ 32 ok_invalid_parameter(MapStatus); \ 33 else \ 34 ok_eq_hex(Status, MapStatus); \ 35 if (NT_SUCCESS(Status)) \ 36 { \ 37 Status = ZwUnmapViewOfSection(ProcessHandle, BaseAddress); \ 38 if (UnmapStatus != IGNORE) ok_eq_hex(Status, UnmapStatus); \ 39 *BaseAddress2 = NULL; \ 40 *ViewSize2 = 0; \ 41 } \ 42 } while (0) \ 43 44#define MmTestMapView(Object, ProcessHandle, BaseAddress2, ZeroBits, CommitSize, SectionOffset, ViewSize2, InheritDisposition, AllocationType, Win32Protect, MapStatus, UnmapStatus) do \ 45 { \ 46 Status = MmMapViewOfSection(Object, ProcessHandle, BaseAddress2, ZeroBits, CommitSize, SectionOffset, ViewSize2, InheritDisposition, AllocationType, Win32Protect); \ 47 ok_eq_hex(Status, MapStatus); \ 48 if (NT_SUCCESS(Status)) \ 49 { \ 50 Status = MmUnmapViewOfSection(ProcessHandle, BaseAddress); \ 51 if (UnmapStatus != IGNORE) ok_eq_hex(Status, UnmapStatus); \ 52 *BaseAddress2 = NULL; \ 53 *ViewSize2 = 0; \ 54 } \ 55 } while (0) \ 56 57#define CheckObject(Handle, Pointers, Handles) do \ 58{ \ 59 PUBLIC_OBJECT_BASIC_INFORMATION ObjectInfo; \ 60 Status = ZwQueryObject(Handle, ObjectBasicInformation, \ 61 &ObjectInfo, sizeof ObjectInfo, NULL); \ 62 ok_eq_hex(Status, STATUS_SUCCESS); \ 63 ok_eq_ulong(ObjectInfo.PointerCount, Pointers); \ 64 ok_eq_ulong(ObjectInfo.HandleCount, Handles); \ 65} while (0) \ 66 67static 68VOID 69KmtInitTestFiles(PHANDLE ReadOnlyFile, PHANDLE WriteOnlyFile, PHANDLE ExecutableFile) 70{ 71 NTSTATUS Status; 72 LARGE_INTEGER FileOffset; 73 IO_STATUS_BLOCK IoStatusBlock; 74 75 //INIT THE READ-ONLY FILE 76 Status = ZwCreateFile(ReadOnlyFile, GENERIC_READ, &NtdllObject, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0); 77 ok_eq_hex(Status, STATUS_SUCCESS); 78 ok(*ReadOnlyFile != NULL, "Couldn't acquire READONLY handle\n"); 79 80 //INIT THE EXECUTABLE FILE 81 Status = ZwCreateFile(ExecutableFile, GENERIC_EXECUTE, &NtdllObject, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0); 82 ok_eq_hex(Status, STATUS_SUCCESS); 83 ok(*ExecutableFile != NULL, "Couldn't acquire EXECUTE handle\n"); 84 85 //INIT THE WRITE-ONLY FILE 86 //TODO: Delete the file when the tests are all executed 87 Status = ZwCreateFile(WriteOnlyFile, (GENERIC_WRITE | SYNCHRONIZE), &KmtestFileObject, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE, FILE_SUPERSEDE, (FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE), NULL, 0); 88 ok_eq_hex(Status, STATUS_SUCCESS); 89 ok_eq_ulongptr(IoStatusBlock.Information, FILE_CREATED); 90 ok(*WriteOnlyFile != NULL, "WriteOnlyFile is NULL\n"); 91 if (!skip(*WriteOnlyFile != NULL, "No WriteOnlyFile\n")) 92 { 93 FileOffset.QuadPart = 0; 94 Status = ZwWriteFile(*WriteOnlyFile, NULL, NULL, NULL, &IoStatusBlock, (PVOID)TestString, TestStringSize, &FileOffset, NULL); 95 ok(Status == STATUS_SUCCESS || Status == STATUS_PENDING, "Status = 0x%08lx\n", Status); 96 Status = ZwWaitForSingleObject(*WriteOnlyFile, FALSE, NULL); 97 ok_eq_hex(Status, STATUS_SUCCESS); 98 ok_eq_ulongptr(IoStatusBlock.Information, TestStringSize); 99 } 100} 101 102static 103VOID 104SimpleErrorChecks(HANDLE FileHandleReadOnly, HANDLE FileHandleWriteOnly, HANDLE ExecutableImg) 105{ 106 NTSTATUS Status; 107 HANDLE WriteSectionHandle; 108 HANDLE ReadOnlySection; 109 HANDLE PageFileSectionHandle; 110 LARGE_INTEGER MaximumSize; 111 LARGE_INTEGER SectionOffset; 112 SIZE_T AllocSize = TestStringSize; 113 SIZE_T ViewSize = 0; 114 PVOID BaseAddress = NULL; 115 PVOID AllocBase = NULL; 116 MaximumSize.QuadPart = TestStringSize; 117 118 //Used for parameters working on file-based section 119 Status = ZwCreateSection(&WriteSectionHandle, SECTION_ALL_ACCESS, NULL, &MaximumSize, PAGE_READWRITE, SEC_COMMIT, FileHandleWriteOnly); 120 ok_eq_hex(Status, STATUS_SUCCESS); 121 122 Status = ZwCreateSection(&ReadOnlySection, SECTION_ALL_ACCESS, NULL, &MaximumSize, PAGE_READONLY, SEC_COMMIT, FileHandleReadOnly); 123 ok_eq_hex(Status, STATUS_SUCCESS); 124 125 //Used for parameters taking effect only on page-file backed section 126 MaximumSize.QuadPart = 5 * MM_ALLOCATION_GRANULARITY; 127 Status = ZwCreateSection(&PageFileSectionHandle, SECTION_ALL_ACCESS, NULL, &MaximumSize, PAGE_READWRITE, SEC_COMMIT, NULL); 128 ok_eq_hex(Status, STATUS_SUCCESS); 129 130 MaximumSize.QuadPart = TestStringSize; 131 132 //section handle 133 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 134 TestMapView((HANDLE)(ULONG_PTR)0xDEADBEEFDEADBEEFull, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_HANDLE, IGNORE); 135 TestMapView(INVALID_HANDLE_VALUE, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_OBJECT_TYPE_MISMATCH, IGNORE); 136 TestMapView(NULL, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_HANDLE, IGNORE); 137 138 //process handle 139 TestMapView(WriteSectionHandle, (HANDLE)(ULONG_PTR)0xDEADBEEFDEADBEEFull, &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_HANDLE, IGNORE); 140 TestMapView(WriteSectionHandle, (HANDLE)NULL, &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_HANDLE, IGNORE); 141 142 //base address 143 BaseAddress = (PVOID)(ULONG_PTR)0x00567A20; 144 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_MAPPED_ALIGNMENT, IGNORE); 145 146 BaseAddress = (PVOID)(ULONG_PTR)0x60000000; 147 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 148 149 BaseAddress = (PVOID)((char *)MmSystemRangeStart + 200); 150 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_3, IGNORE); 151 152 //invalid section handle AND unaligned base address 153 BaseAddress = (PVOID)(ULONG_PTR)0x00567A20; 154 TestMapView((HANDLE)(ULONG_PTR)0xDEADBEEFDEADBEEFull, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_HANDLE, IGNORE); 155 156 //invalid process handle AND unaligned base address 157 BaseAddress = (PVOID)(ULONG_PTR)0x00567A20; 158 TestMapView(WriteSectionHandle, (HANDLE)(ULONG_PTR)0xDEADBEEFDEADBEEFull, &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_HANDLE, IGNORE); 159 160 //try mapping section to an already mapped address 161 Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &AllocBase, 0, &AllocSize, MEM_COMMIT, PAGE_READWRITE); 162 if (!skip(NT_SUCCESS(Status), "Cannot allocate memory\n")) 163 { 164 BaseAddress = AllocBase; 165 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_CONFLICTING_ADDRESSES, IGNORE); 166 Status = ZwFreeVirtualMemory(NtCurrentProcess(), &AllocBase, &AllocSize, MEM_RELEASE); 167 ok_eq_hex(Status, STATUS_SUCCESS); 168 } 169 170 //zero bits 171#ifdef _M_IX86 172 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 1, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 173 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 5, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 174 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, -1, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_4, IGNORE); 175#else 176 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 1, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, GetNTVersion() >= _WIN32_WINNT_WIN8 ? STATUS_INVALID_PARAMETER_4 : STATUS_SUCCESS, STATUS_SUCCESS); 177 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 5, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, GetNTVersion() >= _WIN32_WINNT_WIN8 ? STATUS_INVALID_PARAMETER_4 : STATUS_SUCCESS, STATUS_SUCCESS); 178 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, -1, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, IGNORE); 179#endif 180 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 20, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_NO_MEMORY, IGNORE); 181 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 21, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_NO_MEMORY, IGNORE); 182 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 22, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_4, IGNORE); 183 184 //commit size 185 TestMapView(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 500, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 186 TestMapView(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 187 TestMapView(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, -1, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, IGNORE); 188 TestMapView(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0x10000000, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, IGNORE); 189 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 500, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_5, IGNORE); 190 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 500, NULL, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 191 192 //section offset 193 SectionOffset.QuadPart = 0; 194 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 195 ok_eq_ulonglong(SectionOffset.QuadPart, 0); 196 197 SectionOffset.QuadPart = 0x00040211; //MSDN is wrong, in w2k3 the ZwMapViewOfSection doesn't align offsets automatically 198 TestMapView(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 500, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_MAPPED_ALIGNMENT, IGNORE); 199 200 SectionOffset.QuadPart = -1; 201 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_MAPPED_ALIGNMENT, IGNORE); 202 203 //View Size 204 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 205 206 ViewSize = -1; 207 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_PARAMETER_3, IGNORE); 208 209 ViewSize = TestStringSize+1; 210 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_VIEW_SIZE, IGNORE); 211 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 212 213 ViewSize = TestStringSize; 214 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 215 216 ViewSize = TestStringSize-1; 217 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 218 219 //allocation type 220 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE, STATUS_SUCCESS, STATUS_SUCCESS); 221 TestMapView(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE, STATUS_INVALID_PARAMETER_9, STATUS_SUCCESS); 222 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE, STATUS_INVALID_PARAMETER_9, IGNORE); 223 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, (MEM_LARGE_PAGES | MEM_RESERVE), PAGE_READWRITE, (NTSTATUS)(GetNTVersion() >= _WIN32_WINNT_WIN10 ? STATUS_INVALID_PARAMETER : STATUS_SUCCESS), STATUS_SUCCESS); 224 225 //win32protect 226 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READONLY, STATUS_SUCCESS, STATUS_SUCCESS); 227 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_NOACCESS, STATUS_SUCCESS, STATUS_SUCCESS); 228 TestMapView(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_EXECUTE_WRITECOPY, STATUS_SECTION_PROTECTION, IGNORE); 229 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_SECTION_PROTECTION, IGNORE); 230 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_WRITECOPY, STATUS_SUCCESS, STATUS_SUCCESS); 231 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_EXECUTE_READ, STATUS_SECTION_PROTECTION, IGNORE); 232 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_EXECUTE, STATUS_SECTION_PROTECTION, IGNORE); 233 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READONLY, STATUS_SUCCESS, STATUS_SUCCESS); 234 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_NOACCESS, STATUS_SUCCESS, STATUS_SUCCESS); 235 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, 0, (PAGE_READWRITE | PAGE_READONLY), STATUS_INVALID_PAGE_PROTECTION, IGNORE); 236 TestMapView(ReadOnlySection, NtCurrentProcess(), &BaseAddress, 0, 0, NULL, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READONLY, STATUS_SECTION_PROTECTION, IGNORE); 237 238 ZwClose(WriteSectionHandle); 239 ZwClose(PageFileSectionHandle); 240 ZwClose(ReadOnlySection); 241} 242 243 244static 245VOID 246AdvancedErrorChecks(HANDLE FileHandleReadOnly, HANDLE FileHandleWriteOnly) 247{ 248 NTSTATUS Status; 249 PVOID BaseAddress; 250 HANDLE FileSectionHandle; 251 LARGE_INTEGER SectionOffset; 252 LARGE_INTEGER MaximumSize; 253 SIZE_T ViewSize = 0; 254 PVOID SectionObject; 255 256 MaximumSize.QuadPart = TestStringSize; 257 //Used for parameters working on file-based section 258 Status = ZwCreateSection(&FileSectionHandle, SECTION_ALL_ACCESS, NULL, &MaximumSize, PAGE_READWRITE, SEC_COMMIT, FileHandleWriteOnly); 259 ok_eq_hex(Status, STATUS_SUCCESS); 260 261 Status = ObReferenceObjectByHandle(FileSectionHandle, 262 STANDARD_RIGHTS_ALL, 263 NULL, 264 KernelMode, 265 &SectionObject, 266 NULL); 267 268 ok_eq_hex(Status, STATUS_SUCCESS); 269 270 //Bypassing Zw function calls mean bypassing the alignment checks which are not crucial for the branches being tested here 271 272 //test first conditional branch 273 ViewSize = -1; 274#ifdef _M_IX86 275 NTSTATUS MapStatus; 276 277 switch (GetNTVersion()) 278 { 279 case _WIN32_WINNT_WIN8: 280 case _WIN32_WINNT_WINBLUE: 281 MapStatus = STATUS_INVALID_VIEW_SIZE; 282 break; 283 case _WIN32_WINNT_WIN10: 284 MapStatus = STATUS_CONFLICTING_ADDRESSES; 285 break; 286 default: 287 MapStatus = STATUS_SUCCESS; 288 break; 289 } 290 291 MmTestMapView(SectionObject, PsGetCurrentProcess(), &BaseAddress, 0, TestStringSize, 292 &SectionOffset, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE, MapStatus, IGNORE); 293#else 294 MmTestMapView(SectionObject, PsGetCurrentProcess(), &BaseAddress, 0, TestStringSize, 295 &SectionOffset, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE, STATUS_INVALID_VIEW_SIZE, IGNORE); 296#endif 297 298 //test second conditional branch 299 ViewSize = 1; 300 SectionOffset.QuadPart = TestStringSize; 301 MmTestMapView(SectionObject, PsGetCurrentProcess(), &BaseAddress, 0, TestStringSize, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE, STATUS_INVALID_VIEW_SIZE, IGNORE); 302 303 ObDereferenceObject(SectionObject); 304 ZwClose(FileSectionHandle); 305} 306 307static 308SIZE_T 309CompareFileContents(HANDLE FileHandle, ULONG BufferLength, PVOID Buffer) 310{ 311 NTSTATUS Status; 312 LARGE_INTEGER ByteOffset; 313 IO_STATUS_BLOCK IoStatusBlock; 314 PVOID FileContent; 315 SIZE_T Match; 316 317 Match = 0; 318 ByteOffset.QuadPart = 0; 319 320 FileContent = ExAllocatePoolWithTag(PagedPool, BufferLength, 'Test'); 321 if (!skip((FileContent != NULL), "Error allocating memory for FileContent\n")) 322 { 323 Status = ZwReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, FileContent, BufferLength, &ByteOffset, NULL); 324 ok(Status == STATUS_SUCCESS || Status == STATUS_PENDING, "Unexpected status (0x%X).\n", Status); 325 ok_eq_ulongptr(IoStatusBlock.Information, BufferLength); 326 327 Match = 0; 328 Match = RtlCompareMemory(FileContent, Buffer, BufferLength); 329 ExFreePoolWithTag(FileContent, 'Test'); 330 } 331 332 return Match; 333} 334 335 336static 337VOID 338NTAPI 339SystemProcessWorker(PVOID StartContext) 340{ 341 NTSTATUS Status; 342 PVOID BaseAddress; 343 HANDLE SectionHandle; 344 SIZE_T ViewSize; 345 SIZE_T Match; 346 LARGE_INTEGER SectionOffset; 347 OBJECT_ATTRIBUTES ObjectAttributes; 348 ULONG PtrCnt; 349 350 UNREFERENCED_PARAMETER(StartContext); 351 352 if (GetNTVersion() >= _WIN32_WINNT_WIN8) 353#ifdef _M_IX86 354 PtrCnt = 64; 355#else 356 PtrCnt = 65536; 357#endif 358 else 359 PtrCnt = 4; 360 361 BaseAddress = NULL; 362 ViewSize = TestStringSize; 363 SectionOffset.QuadPart = 0; 364 365 InitializeObjectAttributes(&ObjectAttributes, &SharedSectionName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); 366 Status = ZwOpenSection(&SectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes); 367 if (!skip(NT_SUCCESS(Status), "Error acquiring handle to section. Error = %p\n", Status)) 368 { 369 CheckObject(SectionHandle, PtrCnt, 2); 370 Status = ZwMapViewOfSection(SectionHandle, NtCurrentProcess(), &BaseAddress, 0, TestStringSize, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); 371 if (GetNTVersion() >= _WIN32_WINNT_WIN8) 372 PtrCnt -= 2; 373 374 //make sure ZwMapViewofSection doesn't touch the section ref counts. 375 CheckObject(SectionHandle, PtrCnt, 2); 376 if (GetNTVersion() >= _WIN32_WINNT_WIN8) 377 PtrCnt--; 378 379 if (!skip(NT_SUCCESS(Status), "Error mapping page file view in system process. Error = %p\n", Status)) 380 { 381 Match = RtlCompareMemory(BaseAddress, TestString, TestStringSize); 382 ok_eq_size(Match, TestStringSize); 383 384 RtlCopyMemory(BaseAddress, NEW_CONTENT, NEW_CONTENT_LEN); 385 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 386 387 //make sure ZwMapViewofSection doesn't touch the section ref counts. 388 CheckObject(SectionHandle, PtrCnt, 2); 389 } 390 391 ZwClose(SectionHandle); 392 } 393 394 PsTerminateSystemThread(STATUS_SUCCESS); 395} 396 397 398static 399VOID 400BehaviorChecks(HANDLE FileHandleReadOnly, HANDLE FileHandleWriteOnly) 401{ 402 NTSTATUS Status; 403 PVOID BaseAddress = NULL; 404 PVOID ThreadObject; 405 HANDLE WriteSectionHandle; 406 HANDLE SysThreadHandle; 407 OBJECT_ATTRIBUTES ObjectAttributes; 408 LARGE_INTEGER SectionOffset; 409 LARGE_INTEGER MaximumSize; 410 SIZE_T Match; 411 SIZE_T ViewSize = 0; 412 ULONG PtrCnt; 413 414 if (GetNTVersion() >= _WIN32_WINNT_WIN8) 415#ifdef _M_IX86 416 PtrCnt = 34; 417#else 418 PtrCnt = 32770; 419#endif 420 else 421 PtrCnt = 3; 422 423 InitializeObjectAttributes(&ObjectAttributes, &SharedSectionName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); 424 MaximumSize.QuadPart = TestStringSize; 425 SectionOffset.QuadPart = 0; 426 427 Status = ZwCreateSection(&WriteSectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes, &MaximumSize, PAGE_READWRITE, SEC_COMMIT, FileHandleWriteOnly); 428 CheckObject(WriteSectionHandle, PtrCnt, 1); 429 if (GetNTVersion() >= _WIN32_WINNT_WIN8) 430 PtrCnt -= 2; 431 ok(NT_SUCCESS(Status), "Error creating write section from file. Error = %p\n", Status); 432 433 //check for section reading/writing by comparing section content to a well-known value. 434 Status = ZwMapViewOfSection(WriteSectionHandle, NtCurrentProcess() ,&BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); 435 CheckObject(WriteSectionHandle, PtrCnt, 1); 436 if (!skip(NT_SUCCESS(Status), "Error mapping view with READ/WRITE priv. Error = %p\n", Status)) 437 { 438 Match = RtlCompareMemory(BaseAddress, TestString, TestStringSize); 439 ok_eq_size(Match, TestStringSize); 440 441 //now check writing to section 442 RtlCopyMemory(BaseAddress, NEW_CONTENT, NEW_CONTENT_LEN); 443 444 Match = RtlCompareMemory(BaseAddress, NEW_CONTENT, NEW_CONTENT_LEN); 445 ok_eq_size(Match, NEW_CONTENT_LEN); 446 447 //check to see if the contents have been flushed to the actual file on disk. 448 Match = CompareFileContents(FileHandleWriteOnly, NEW_CONTENT_LEN, NEW_CONTENT); 449 ok_eq_size(Match, NEW_CONTENT_LEN); 450 451 //bring everything back to normal 452 RtlCopyMemory(BaseAddress, TestString, TestStringSize); 453 454 //Initiate an external thread to modify the file 455 InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); 456 Status = PsCreateSystemThread(&SysThreadHandle, STANDARD_RIGHTS_ALL, &ObjectAttributes, NULL, NULL, SystemProcessWorker, NULL); 457 if (!skip(NT_SUCCESS(Status), "Error creating System thread. Error = %p\n", Status)) 458 { 459 Status = ObReferenceObjectByHandle(SysThreadHandle, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &ThreadObject, NULL); 460 if (!skip(NT_SUCCESS(Status), "Error getting reference to System thread when testing file-backed section\n")) 461 { 462 //wait until the system thread actually terminates 463 KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, NULL); 464 465 //no longer need the thread object 466 ObDereferenceObject(ThreadObject); 467 468 //test for bi-directional access to the shared page file 469 Match = RtlCompareMemory(BaseAddress, NEW_CONTENT, NEW_CONTENT_LEN); 470 ok_eq_size(Match, NEW_CONTENT_LEN); 471 472 //bring everything back to normal, again 473 RtlCopyMemory(BaseAddress, TestString, TestStringSize); 474 } 475 } 476 477 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 478 } 479 480 //Try to write to read-only mapped view 481 BaseAddress = NULL; 482 ViewSize = 0; 483 SectionOffset.QuadPart = 0; 484 Status = ZwMapViewOfSection(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READONLY); 485 if (!skip(NT_SUCCESS(Status), "Error mapping view with READ priv. Error = %p\n", Status)) 486 { 487 Match = RtlCompareMemory(BaseAddress, TestString, TestStringSize); 488 ok_eq_size(Match, TestStringSize); 489 490 KmtStartSeh() 491 RtlCopyMemory(BaseAddress, NEW_CONTENT, NEW_CONTENT_LEN); 492 KmtEndSeh(STATUS_ACCESS_VIOLATION); 493 494 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 495 } 496 497 //try to access forbidden memory 498 BaseAddress = NULL; 499 ViewSize = 0; 500 SectionOffset.QuadPart = 0; 501 Status = ZwMapViewOfSection(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_NOACCESS); 502 if (!skip(NT_SUCCESS(Status), "Error mapping view with PAGE_NOACCESS priv. Error = %p\n", Status)) 503 { 504 KmtStartSeh() 505 RtlCompareMemory(BaseAddress, TestString, TestStringSize); 506 KmtEndSeh(STATUS_ACCESS_VIOLATION); 507 508 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 509 } 510 511 //try to access guarded memory 512 BaseAddress = NULL; 513 ViewSize = 0; 514 SectionOffset.QuadPart = 0; 515 Status = ZwMapViewOfSection(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, 0, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_GUARD | PAGE_READWRITE); 516 if (!skip(NT_SUCCESS(Status), "Error mapping view with PAGE_GUARD priv. Error = %p\n", Status)) 517 { 518 KmtStartSeh() 519 RtlCompareMemory(BaseAddress, TestString, TestStringSize); 520 KmtEndSeh(STATUS_GUARD_PAGE_VIOLATION); 521 522 KmtStartSeh() 523 RtlCompareMemory(BaseAddress, TestString, TestStringSize); 524 KmtEndSeh(STATUS_SUCCESS); 525 526 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 527 } 528 529 ZwClose(WriteSectionHandle); 530 531 //section created with sec_reserve should not be commited. 532 BaseAddress = NULL; 533 ViewSize = 0; 534 SectionOffset.QuadPart = 0; 535 Status = ZwCreateSection(&WriteSectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes, &MaximumSize, PAGE_READWRITE, SEC_RESERVE, FileHandleWriteOnly); 536 if (!skip(NT_SUCCESS(Status), "Error creating page file section. Error = %p\n", Status)) 537 { 538 Status = ZwMapViewOfSection(WriteSectionHandle, NtCurrentProcess(), &BaseAddress, 0, TestStringSize, &SectionOffset, &ViewSize, ViewUnmap, MEM_RESERVE, PAGE_READWRITE); 539 if (!skip(NT_SUCCESS(Status), "Error mapping page file view. Error = %p\n", Status)) 540 { 541 //check also the SEC_COMMIT flag 542 /* This test proves that MSDN is once again wrong 543 * https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-createfilemappingw states that SEC_RESERVE 544 * should cause the allocated memory for the view to be reserved but in fact it is always committed. 545 * It fails also on windows. 546 */ 547 Test_NtQueryVirtualMemory(BaseAddress, PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE); 548 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 549 } 550 551 ZwClose(WriteSectionHandle); 552 } 553} 554 555 556static 557VOID 558PageFileBehaviorChecks() 559{ 560 NTSTATUS Status; 561 LARGE_INTEGER MaxSectionSize; 562 LARGE_INTEGER SectionOffset; 563 HANDLE PageFileSectionHandle; 564 PVOID BaseAddress; 565 SIZE_T ViewSize; 566 SIZE_T Match; 567 PVOID ThreadObject; 568 OBJECT_ATTRIBUTES ObjectAttributes; 569 ULONG PtrCnt; 570 571 if (GetNTVersion() >= _WIN32_WINNT_WIN8) 572#ifdef _M_IX86 573 PtrCnt = 34; 574#else 575 PtrCnt = 32770; 576#endif 577 else 578 PtrCnt = 3; 579 580 MaxSectionSize.QuadPart = TestStringSize; 581 SectionOffset.QuadPart = 0; 582 PageFileSectionHandle = INVALID_HANDLE_VALUE; 583 BaseAddress = NULL; 584 ViewSize = TestStringSize; 585 InitializeObjectAttributes(&ObjectAttributes, &SharedSectionName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); 586 587 //test memory sharing between 2 different processes 588 Status = ZwCreateSection(&PageFileSectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes, &MaxSectionSize, PAGE_READWRITE, SEC_COMMIT, NULL); 589 if (!skip(NT_SUCCESS(Status), "Error creating page file section. Error = %p\n", Status)) 590 { 591 CheckObject(PageFileSectionHandle, PtrCnt, 1); 592 Status = ZwMapViewOfSection(PageFileSectionHandle, NtCurrentProcess(), &BaseAddress, 0, TestStringSize, &SectionOffset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); 593 if (GetNTVersion() >= _WIN32_WINNT_WIN8) 594 PtrCnt -= 2; 595 if (!skip(NT_SUCCESS(Status), "Error mapping page file view. Error = %p\n", Status)) 596 { 597 HANDLE SysThreadHandle; 598 599 CheckObject(PageFileSectionHandle, PtrCnt, 1); 600 601 //check also the SEC_COMMIT flag 602 Test_NtQueryVirtualMemory(BaseAddress, PAGE_SIZE, MEM_COMMIT, PAGE_READWRITE); 603 604 RtlCopyMemory(BaseAddress, TestString, TestStringSize); 605 606 InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); 607 Status = PsCreateSystemThread(&SysThreadHandle, STANDARD_RIGHTS_ALL, &ObjectAttributes, NULL, NULL, SystemProcessWorker, NULL); 608 609 if (!skip(NT_SUCCESS(Status), "Error creating System thread. Error = %p\n", Status)) 610 { 611 Status = ObReferenceObjectByHandle(SysThreadHandle, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &ThreadObject, NULL); 612 if (!skip(NT_SUCCESS(Status), "Error getting reference to System thread when testing pagefile-backed section\n")) 613 { 614 //wait until the system thread actually terminates 615 KeWaitForSingleObject(ThreadObject, Executive, KernelMode, FALSE, NULL); 616 617 //no longer need the thread object 618 ObDereferenceObject(ThreadObject); 619 620 //test for bi-directional access to the shared page file 621 Match = RtlCompareMemory(BaseAddress, NEW_CONTENT, NEW_CONTENT_LEN); 622 ok_eq_size(Match, NEW_CONTENT_LEN); 623 } 624 } 625 ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); 626 } 627 ZwClose(PageFileSectionHandle); 628 } 629} 630 631 632START_TEST(ZwMapViewOfSection) 633{ 634 HANDLE FileHandleReadOnly = NULL; 635 HANDLE FileHandleWriteOnly = NULL; 636 HANDLE ExecutableFileHandle = NULL; 637 638 InitializeObjectAttributes(&NtdllObject, &FileReadOnlyPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); 639 InitializeObjectAttributes(&KmtestFileObject, &WritableFilePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); 640 InitializeObjectAttributes(&NtoskrnlFileObject, &NtosImgPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); 641 642 KmtInitTestFiles(&FileHandleReadOnly, &FileHandleWriteOnly, &ExecutableFileHandle); 643 644 SimpleErrorChecks(FileHandleReadOnly, FileHandleWriteOnly, ExecutableFileHandle); 645 AdvancedErrorChecks(FileHandleReadOnly, FileHandleWriteOnly); 646 BehaviorChecks(FileHandleReadOnly, FileHandleWriteOnly); 647 PageFileBehaviorChecks(); 648 649 if (FileHandleReadOnly) 650 ZwClose(FileHandleReadOnly); 651 652 if (FileHandleWriteOnly) 653 ZwClose(FileHandleWriteOnly); 654 655 if (ExecutableFileHandle) 656 ZwClose(ExecutableFileHandle); 657}