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