Reactos
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}