From 6bea3b076dbcc41b1c9abd556da8a75e6b73748d Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Sun, 18 Jun 2017 08:00:29 +0000 Subject: [PATCH] [KMTESTS:MM] - Test unaligned address and addresses close to MmHighestUserAddress in MmMapLockedPagesSpecifyCache test CORE-13444 svn path=/trunk/; revision=75084 --- .../ntos_mm/MmMapLockedPagesSpecifyCache.h | 2 + .../MmMapLockedPagesSpecifyCache_drv.c | 26 ++++-- .../MmMapLockedPagesSpecifyCache_user.c | 81 +++++++++++++++++-- 3 files changed, 98 insertions(+), 11 deletions(-) diff --git a/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache.h b/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache.h index 6b4ecd668e4..fcc0abf940b 100644 --- a/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache.h +++ b/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache.h @@ -14,6 +14,7 @@ typedef struct _QUERY_BUFFER USHORT Length; PVOID Buffer; BOOLEAN Cached; + NTSTATUS Status; } QUERY_BUFFER, *PQUERY_BUFFER; typedef struct _READ_BUFFER @@ -25,6 +26,7 @@ typedef struct _READ_BUFFER #define IOCTL_QUERY_BUFFER 1 #define IOCTL_READ_BUFFER 2 +#define IOCTL_CLEAN 3 #define WRITE_PATTERN 0xA4A5A6A7 diff --git a/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_drv.c b/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_drv.c index 95d1eec1928..78f250b40d0 100644 --- a/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_drv.c +++ b/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_drv.c @@ -121,7 +121,7 @@ TestMessageHandler( TestCleanEverything(); - ok(ExGetPreviousMode() == UserMode, "Not comming from umode!\n"); + ok(ExGetPreviousMode() == UserMode, "Not coming from umode!\n"); if (!skip(Buffer && InLength >= sizeof(QUERY_BUFFER) && *OutLength >= sizeof(QUERY_BUFFER), "Cannot read/write from/to buffer!\n")) { PQUERY_BUFFER QueryBuffer; @@ -178,15 +178,26 @@ TestMessageHandler( SehStatus = STATUS_SUCCESS; _SEH2_TRY { - CurrentUser = MmMapLockedPagesSpecifyCache(CurrentMdl, UserMode, CacheType, NULL, FALSE, NormalPagePriority); + CurrentUser = MmMapLockedPagesSpecifyCache(CurrentMdl, UserMode, CacheType, QueryBuffer->Buffer, FALSE, NormalPagePriority); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SehStatus = _SEH2_GetExceptionCode(); } _SEH2_END; - ok_eq_hex(SehStatus, STATUS_SUCCESS); - ok(CurrentUser != NULL, "MmMapLockedPagesSpecifyCache failed!\n"); + if (QueryBuffer->Status != -1) + { + ok_eq_hex(SehStatus, QueryBuffer->Status); + if (NT_SUCCESS(QueryBuffer->Status)) + { + ok(CurrentUser != NULL, "MmMapLockedPagesSpecifyCache failed!\n"); + } + else + { + ok(CurrentUser == NULL, "MmMapLockedPagesSpecifyCache succeeded!\n"); + } + } + QueryBuffer->Status = SehStatus; } else { @@ -208,7 +219,7 @@ TestMessageHandler( ok_eq_size(*OutLength, 0); ok(CurrentMdl != NULL, "MDL is not in use!\n"); - if (!skip(Buffer && InLength >= sizeof(QUERY_BUFFER), "Cannot read from buffer!\n")) + if (!skip(Buffer && InLength >= sizeof(READ_BUFFER), "Cannot read from buffer!\n")) { PREAD_BUFFER ReadBuffer; @@ -237,6 +248,11 @@ TestMessageHandler( break; } + case IOCTL_CLEAN: + { + TestCleanEverything(); + break; + } default: ok(0, "Got an unknown message! DeviceObject=%p, ControlCode=%lu, Buffer=%p, In=%lu, Out=%lu bytes\n", DeviceObject, ControlCode, Buffer, InLength, *OutLength); diff --git a/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_user.c b/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_user.c index 01ab3b454d3..0fe781f7d1a 100644 --- a/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_user.c +++ b/rostests/kmtests/ntos_mm/MmMapLockedPagesSpecifyCache_user.c @@ -6,9 +6,13 @@ */ #include +#include #include "MmMapLockedPagesSpecifyCache.h" +#define ALIGN_DOWN_BY(size, align) \ + ((ULONG_PTR)(size) & ~((ULONG_PTR)(align) - 1)) + #define SET_BUFFER_LENGTH(Var, Length) \ { \ C_ASSERT(((Length) % sizeof(ULONG)) == 0); \ @@ -20,6 +24,7 @@ QueryBuffer.Length = BufferLength; \ QueryBuffer.Buffer = NULL; \ QueryBuffer.Cached = UseCache; \ + QueryBuffer.Status = STATUS_SUCCESS; \ } #define FILL_READ_BUFFER(QueryBuffer, ReadBuffer) \ @@ -78,6 +83,9 @@ START_TEST(MmMapLockedPagesSpecifyCache) DWORD Length; USHORT i; USHORT BufferLength; + SYSTEM_BASIC_INFORMATION BasicInfo; + NTSTATUS Status; + ULONG_PTR HighestAddress; KmtLoadDriver(L"MmMapLockedPagesSpecifyCache", FALSE); KmtOpenDriver(); @@ -180,9 +188,7 @@ START_TEST(MmMapLockedPagesSpecifyCache) // more than 2 pages SET_BUFFER_LENGTH(BufferLength, 2 * 4096 + 2048); - QueryBuffer.Length = BufferLength; - QueryBuffer.Buffer = NULL; - QueryBuffer.Cached = FALSE; + FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); Length = sizeof(QUERY_BUFFER); ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); ok_eq_int(QueryBuffer.Length, BufferLength); @@ -193,9 +199,7 @@ START_TEST(MmMapLockedPagesSpecifyCache) FILL_READ_BUFFER(QueryBuffer, ReadBuffer); ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); - QueryBuffer.Length = BufferLength; - QueryBuffer.Buffer = NULL; - QueryBuffer.Cached = TRUE; + FILL_QUERY_BUFFER(QueryBuffer, BufferLength, TRUE); Length = sizeof(QUERY_BUFFER); ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); ok_eq_int(QueryBuffer.Length, BufferLength); @@ -206,6 +210,71 @@ START_TEST(MmMapLockedPagesSpecifyCache) FILL_READ_BUFFER(QueryBuffer, ReadBuffer); ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); + // ask for a specific address (we know that ReadBuffer.Buffer is free) + SET_BUFFER_LENGTH(BufferLength, 4096); + FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); + QueryBuffer.Buffer = ReadBuffer.Buffer; + Length = sizeof(QUERY_BUFFER); + ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); + ok_eq_int(QueryBuffer.Length, BufferLength); + ok(QueryBuffer.Buffer == ReadBuffer.Buffer, "Buffer is NULL\n"); + CHECK_ALLOC(QueryBuffer.Buffer, BufferLength); + + Length = 0; + FILL_READ_BUFFER(QueryBuffer, ReadBuffer); + ok(KmtSendBufferToDriver(IOCTL_READ_BUFFER, &ReadBuffer, sizeof(READ_BUFFER), &Length) == ERROR_SUCCESS, "\n"); + + // ask for an unaligned address + SET_BUFFER_LENGTH(BufferLength, 4096); + FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); + QueryBuffer.Buffer = (PVOID)((ULONG_PTR)ReadBuffer.Buffer + 2048); + QueryBuffer.Status = STATUS_INVALID_ADDRESS; + Length = sizeof(QUERY_BUFFER); + ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); + ok_eq_int(QueryBuffer.Length, BufferLength); + ok(QueryBuffer.Buffer == NULL, "Buffer is %p\n", QueryBuffer.Buffer); + + Length = 0; + ok(KmtSendBufferToDriver(IOCTL_CLEAN, NULL, 0, &Length) == ERROR_SUCCESS, "\n"); + + // get system info for MmHighestUserAddress + Status = NtQuerySystemInformation(SystemBasicInformation, + &BasicInfo, + sizeof(BasicInfo), + NULL); + ok_eq_hex(Status, STATUS_SUCCESS); + trace("MaximumUserModeAddress: %lx\n", BasicInfo.MaximumUserModeAddress); + HighestAddress = ALIGN_DOWN_BY(BasicInfo.MaximumUserModeAddress, PAGE_SIZE); + + // near MmHighestUserAddress + SET_BUFFER_LENGTH(BufferLength, 4096); + FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); + QueryBuffer.Buffer = (PVOID)(HighestAddress - 15 * PAGE_SIZE); // 7ffe0000 + QueryBuffer.Status = STATUS_INVALID_ADDRESS; + trace("QueryBuffer.Buffer %p\n", QueryBuffer.Buffer); + Length = sizeof(QUERY_BUFFER); + ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); + ok_eq_int(QueryBuffer.Length, BufferLength); + ok(QueryBuffer.Buffer == NULL, "Buffer is %p\n", QueryBuffer.Buffer); + + Length = 0; + ok(KmtSendBufferToDriver(IOCTL_CLEAN, NULL, 0, &Length) == ERROR_SUCCESS, "\n"); + + // far enough away from MmHighestUserAddress + SET_BUFFER_LENGTH(BufferLength, 4096); + FILL_QUERY_BUFFER(QueryBuffer, BufferLength, FALSE); + QueryBuffer.Buffer = (PVOID)(HighestAddress - 16 * PAGE_SIZE); // 7ffdf000 + QueryBuffer.Status = -1; + trace("QueryBuffer.Buffer %p\n", QueryBuffer.Buffer); + Length = sizeof(QUERY_BUFFER); + ok(KmtSendBufferToDriver(IOCTL_QUERY_BUFFER, &QueryBuffer, sizeof(QUERY_BUFFER), &Length) == ERROR_SUCCESS, "\n"); + ok_eq_int(QueryBuffer.Length, BufferLength); + ok(QueryBuffer.Status == STATUS_SUCCESS || + QueryBuffer.Status == STATUS_CONFLICTING_ADDRESSES, "Status = %lx\n", QueryBuffer.Status); + + Length = 0; + ok(KmtSendBufferToDriver(IOCTL_CLEAN, NULL, 0, &Length) == ERROR_SUCCESS, "\n"); + KmtCloseDriver(); KmtUnloadDriver(); }