Added patch to fix crash of winedevice when relocation entry crosses page boundary.

This commit is contained in:
Sebastian Lackner 2014-11-10 04:09:18 +01:00
parent 475485ce5b
commit c3920efc17
5 changed files with 121 additions and 1 deletions

View File

@ -39,7 +39,7 @@ Wine. All those differences are also documented on the
Included bug fixes and improvements
===================================
**Bugfixes and features included in the next upcoming release [13]:**
**Bugfixes and features included in the next upcoming release [14]:**
* Add stub for NtSetLdtEntries/ZwSetLdtEntries ([Wine Bug #26268](https://bugs.winehq.org/show_bug.cgi?id=26268))
* Add stubs for vectored continue handler ([Wine Bug #30572](https://bugs.winehq.org/show_bug.cgi?id=30572))
@ -49,6 +49,7 @@ Included bug fixes and improvements
* Exception during start of fr-043 caused by missing DXTn support ([Wine Bug #37391](https://bugs.winehq.org/show_bug.cgi?id=37391))
* FairplayKD.sys needs KeSetSystemAffinityThread ([Wine Bug #36822](https://bugs.winehq.org/show_bug.cgi?id=36822))
* Fix crash of Trine Demo on start ([Wine Bug #19231](https://bugs.winehq.org/show_bug.cgi?id=19231))
* Fix crash of winedevice when relocation entry crosses page boundary ([Wine Bug #28254](https://bugs.winehq.org/show_bug.cgi?id=28254))
* Fix texture corruption in CSI: Fatal Conspiracy ([Wine Bug #33768](https://bugs.winehq.org/show_bug.cgi?id=33768))
* MSVCRT crashes when NULL is passed as string to atof or strtod ([Wine Bug #32550](https://bugs.winehq.org/show_bug.cgi?id=32550))
* Return correct values for GetThreadTimes function ([Wine Bug #20230](https://bugs.winehq.org/show_bug.cgi?id=20230))

1
debian/changelog vendored
View File

@ -13,6 +13,7 @@ wine-compholio (1.7.31) UNRELEASED; urgency=low
* Added patch with stubs for vectored continue handler functions.
* Added patch to fix wglDescribePixelFormat when NULL is passed as pixel format descriptor.
* Added patch to allow NULL pointer for optional arguments of D3DXIntersectTri.
* Added patch to fix crash of winedevice when relocation entry crosses page boundary.
* Removed patch for iphlpapi stub functions (accepted upstream).
* Removed patches for FindFirstFileExW (accepted upstream).
* Removed patches for TLB dependencies lookup in resources (accepted upstream).

View File

@ -101,6 +101,7 @@ PATCHLIST := \
winebuild-LinkerVersion.ok \
wined3d-DXTn.ok \
wined3d-Revert_PixelFormat.ok \
winedevice-Fix_Relocation.ok \
winemenubuilder-Desktop_Icon_Path.ok \
winepulse-PulseAudio_Support.ok \
winex11-CandidateWindowPos.ok \
@ -1751,6 +1752,24 @@ wined3d-Revert_PixelFormat.ok:
echo '+ { "wined3d-Revert_PixelFormat", "Ken Thomases", "Revert wined3d pixelformat changes." },'; \
) > wined3d-Revert_PixelFormat.ok
# Patchset winedevice-Fix_Relocation
# |
# | Included patches:
# | * Avoid invalid memory access when relocation block addresses memory outside of the current page. [by Sebastian Lackner]
# |
# | This patchset fixes the following Wine bugs:
# | * [#28254] Fix crash of winedevice when relocation entry crosses page boundary
# |
# | Modified files:
# | * programs/winedevice/device.c
# |
.INTERMEDIATE: winedevice-Fix_Relocation.ok
winedevice-Fix_Relocation.ok:
$(call APPLY_FILE,winedevice-Fix_Relocation/0001-winedevice-Avoid-invalid-memory-access-when-relocati.patch)
@( \
echo '+ { "winedevice-Fix_Relocation", "Sebastian Lackner", "Avoid invalid memory access when relocation block addresses memory outside of the current page." },'; \
) > winedevice-Fix_Relocation.ok
# Patchset winemenubuilder-Desktop_Icon_Path
# |
# | Included patches:

View File

@ -0,0 +1,95 @@
From 2e1fed5c492efaeaab25f61ed0640230f8415750 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Mon, 10 Nov 2014 04:05:38 +0100
Subject: winedevice: Avoid invalid memory access when relocation block
addresses memory outside of the current page.
---
programs/winedevice/device.c | 48 ++++++++++++++++++++++++++++++++++++++------
1 file changed, 42 insertions(+), 6 deletions(-)
diff --git a/programs/winedevice/device.c b/programs/winedevice/device.c
index 72bc124..b4736b3 100644
--- a/programs/winedevice/device.c
+++ b/programs/winedevice/device.c
@@ -61,6 +61,38 @@ static LDR_MODULE *find_ldr_module( HMODULE module )
return NULL;
}
+/* change permissions of a specific memory range, save original permissions */
+static void virtual_protect_save( void *addr, SIZE_T size, ULONG new_prot, ULONG *old_prot )
+{
+ SYSTEM_BASIC_INFORMATION info;
+ UINT i = 0;
+
+ NtQuerySystemInformation( SystemBasicInformation, &info, sizeof(info), NULL );
+ while (size)
+ {
+ SIZE_T block_size = min( size, info.PageSize - ((UINT_PTR)addr & (info.PageSize - 1)) );
+ VirtualProtect( addr, block_size, new_prot, &old_prot[i++] );
+ addr = (void *)((char *)addr + block_size);
+ size -= block_size;
+ }
+}
+
+/* restore permissions for a specific memory range */
+static void virtual_protect_load( void *addr, SIZE_T size, ULONG *old_prot )
+{
+ SYSTEM_BASIC_INFORMATION info;
+ UINT i = 0;
+
+ NtQuerySystemInformation( SystemBasicInformation, &info, sizeof(info), NULL );
+ while (size)
+ {
+ SIZE_T block_size = min( size, info.PageSize - ((UINT_PTR)addr & (info.PageSize - 1)) );
+ VirtualProtect( addr, block_size, old_prot[i++], NULL );
+ addr = (void *)((char *)addr + block_size);
+ size -= block_size;
+ }
+}
+
/* load the driver module file */
static HMODULE load_driver_module( const WCHAR *name )
{
@@ -84,7 +116,7 @@ static HMODULE load_driver_module( const WCHAR *name )
if (nt->OptionalHeader.SectionAlignment < info.PageSize ||
!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
{
- DWORD old;
+ DWORD old_prot[3];
IMAGE_BASE_RELOCATION *rel, *end;
if ((rel = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &size )))
@@ -92,20 +124,24 @@ static HMODULE load_driver_module( const WCHAR *name )
WINE_TRACE( "%s: relocating from %p to %p\n",
wine_dbgstr_w(name), (char *)module - delta, module );
end = (IMAGE_BASE_RELOCATION *)((char *)rel + size);
- while (rel < end && rel->SizeOfBlock)
+ while (rel < end - 1 && rel->SizeOfBlock)
{
void *page = (char *)module + rel->VirtualAddress;
- VirtualProtect( page, info.PageSize, PAGE_EXECUTE_READWRITE, &old );
+ /* LdrProcessRelocationBlock can access the memory range from page - (page + 0xfff + 8), so
+ * changing permissions of a single page is not sufficient. We assume here that the minimum
+ * page size is 0x1000, so we have to save/restore two or three pages, depending on the
+ * virtual address. */
+ virtual_protect_save( page, 0xfff + 8, PAGE_EXECUTE_READWRITE, old_prot );
rel = LdrProcessRelocationBlock( page, (rel->SizeOfBlock - sizeof(*rel)) / sizeof(USHORT),
(USHORT *)(rel + 1), delta );
- if (old != PAGE_EXECUTE_READWRITE) VirtualProtect( page, info.PageSize, old, NULL );
+ virtual_protect_load( page, 0xfff + 8, old_prot );
if (!rel) goto error;
}
/* make sure we don't try again */
size = FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + nt->FileHeader.SizeOfOptionalHeader;
- VirtualProtect( nt, size, PAGE_READWRITE, &old );
+ VirtualProtect( nt, size, PAGE_READWRITE, &old_prot[0] );
nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
- VirtualProtect( nt, size, old, NULL );
+ VirtualProtect( nt, size, old_prot[0], NULL );
}
}
--
2.1.3

View File

@ -0,0 +1,4 @@
Author: Sebastian Lackner
Subject: Avoid invalid memory access when relocation block addresses memory outside of the current page.
Revision: 1
Fixes: [28254] Fix crash of winedevice when relocation entry crosses page boundary