Use MmMapIoSpaceEx instead of MmMapIoSpace

Disable execution bit on mapping improving security.

MmMapIoSpaceEx is available only in Windows 10 so
to provide binary compatibility detect the new
function dynamically.
Added a separate compatibility file.

Based on a patch by Sandy Stutsman <sstutsma@redhat.com>

Signed-off-by: Sameeh Jubran <sameeh@daynix.com>
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
This commit is contained in:
Frediano Ziglio 2016-09-28 12:31:04 +01:00
parent a86ef3acf8
commit de8062e7b6
5 changed files with 89 additions and 7 deletions

View File

@ -1,6 +1,7 @@
#include "driver.h" #include "driver.h"
#include "qxldod.h" #include "qxldod.h"
#include "qxl_windows.h" #include "qxl_windows.h"
#include "compat.h"
#pragma code_seg("PAGE") #pragma code_seg("PAGE")
@ -1960,17 +1961,18 @@ MapFrameBuffer(
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
*VirtualAddress = MmMapIoSpace(PhysicalAddress, *VirtualAddress = MapIoSpace(PhysicalAddress,
Length, Length,
MmWriteCombined); MmWriteCombined,
PAGE_WRITECOMBINE | PAGE_READWRITE);
if (*VirtualAddress == NULL) if (*VirtualAddress == NULL)
{ {
// The underlying call to MmMapIoSpace failed. This may be because, MmWriteCombined // The underlying call to MmMapIoSpace failed. This may be because, MmWriteCombined
// isn't supported, so try again with MmNonCached // isn't supported, so try again with MmNonCached
*VirtualAddress = MapIoSpace(PhysicalAddress,
*VirtualAddress = MmMapIoSpace(PhysicalAddress, Length,
Length, MmNonCached,
MmNonCached); PAGE_NOCACHE | PAGE_READWRITE);
if (*VirtualAddress == NULL) if (*VirtualAddress == NULL)
{ {
DbgPrint(TRACE_LEVEL_ERROR, ("MmMapIoSpace returned a NULL buffer when trying to allocate %lu bytes", Length)); DbgPrint(TRACE_LEVEL_ERROR, ("MmMapIoSpace returned a NULL buffer when trying to allocate %lu bytes", Length));

62
qxldod/compat.cpp Normal file
View File

@ -0,0 +1,62 @@
#include "driver.h"
#include "compat.h"
static MapIoSpaceFunc DetectMapIoSpace;
MapIoSpaceFunc *MapIoSpace = DetectMapIoSpace;
typedef NTKERNELAPI PVOID MmMapIoSpaceExFunc(
_In_ PHYSICAL_ADDRESS PhysicalAddress,
_In_ SIZE_T NumberOfBytes,
_In_ ULONG Protect
);
static MmMapIoSpaceExFunc *pMmMapIoSpaceEx;
// all functions in this module are paged
#pragma code_seg("PAGE")
// we call MmMapIoSpace only if MmMapIoSpaceEx is not present
// so disable the warning
#pragma warning(push)
#pragma warning(disable:30029)
static PVOID OldMapIoSpace(
_In_ PHYSICAL_ADDRESS PhysicalAddress,
_In_ SIZE_T NumberOfBytes,
_In_ MEMORY_CACHING_TYPE CacheType,
_In_ ULONG Protect
)
{
PAGED_CODE();
return MmMapIoSpace(PhysicalAddress, NumberOfBytes, CacheType);
}
#pragma warning(pop)
static PVOID NewMapIoSpace(
_In_ PHYSICAL_ADDRESS PhysicalAddress,
_In_ SIZE_T NumberOfBytes,
_In_ MEMORY_CACHING_TYPE CacheType,
_In_ ULONG Protect
)
{
PAGED_CODE();
return pMmMapIoSpaceEx(PhysicalAddress, NumberOfBytes, Protect);
}
static PVOID DetectMapIoSpace(
_In_ PHYSICAL_ADDRESS PhysicalAddress,
_In_ SIZE_T NumberOfBytes,
_In_ MEMORY_CACHING_TYPE CacheType,
_In_ ULONG Protect
)
{
PAGED_CODE();
UNICODE_STRING name;
RtlInitUnicodeString(&name, L"MmMapIoSpaceEx");
pMmMapIoSpaceEx = (MmMapIoSpaceExFunc*)MmGetSystemRoutineAddress(&name);
if (pMmMapIoSpaceEx) {
MapIoSpace = NewMapIoSpace;
} else {
MapIoSpace = OldMapIoSpace;
}
return MapIoSpace(PhysicalAddress, NumberOfBytes, CacheType, Protect);
}

10
qxldod/compat.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "BaseObject.h"
typedef PVOID MapIoSpaceFunc(
_In_ PHYSICAL_ADDRESS PhysicalAddress,
_In_ SIZE_T NumberOfBytes,
_In_ MEMORY_CACHING_TYPE CacheType,
_In_ ULONG Protect
);
extern MapIoSpaceFunc *MapIoSpace;

View File

@ -272,12 +272,14 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="BaseObject.h" /> <ClInclude Include="BaseObject.h" />
<ClInclude Include="compat.h" />
<ClInclude Include="driver.h" /> <ClInclude Include="driver.h" />
<ClInclude Include="QxlDod.h" /> <ClInclude Include="QxlDod.h" />
<ClInclude Include="resource.h" /> <ClInclude Include="resource.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="BaseObject.cpp" /> <ClCompile Include="BaseObject.cpp" />
<ClCompile Include="compat.cpp" />
<ClCompile Include="driver.cpp" /> <ClCompile Include="driver.cpp" />
<ClCompile Include="mspace.c" /> <ClCompile Include="mspace.c" />
<ClCompile Include="QxlDod.cpp" /> <ClCompile Include="QxlDod.cpp" />

View File

@ -25,6 +25,9 @@
<ClInclude Include="resource.h"> <ClInclude Include="resource.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="compat.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="driver.h"> <ClInclude Include="driver.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -36,6 +39,9 @@
<ClCompile Include="BaseObject.cpp"> <ClCompile Include="BaseObject.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="compat.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="driver.cpp"> <ClCompile Include="driver.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>