From: "Erich E. Hoover" Subject: [PATCH 1/1] ntdll: Fix mapping sections for applications that map over the section headers. Message-Id: Date: Mon, 20 Feb 2012 08:54:36 -0700 Real Name: Erich Hoover Description: This patch changes the section mapping to first read out the section headers into local memory before mapping any of the sections. Without this patch then the Steam version of Borderlands cannot run since the game maps a section on top of its own section headers (Bug #29031). Changelog: ntdll: Fix mapping sections for applications that map over the section headers. From a03baa21ac6fe72595fd2d2f265113422aece5e4 Mon Sep 17 00:00:00 2001 From: Erich Hoover Date: Fri, 17 Feb 2012 10:41:35 -0700 Subject: ntdll: Fix mapping sections for applications that map over the section headers. --- dlls/ntdll/virtual.c | 19 +++++++++++++++---- 1 files changed, 15 insertions(+), 4 deletions(-) diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 717917d..a59b2bb 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -1122,7 +1122,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz { IMAGE_DOS_HEADER *dos; IMAGE_NT_HEADERS *nt; - IMAGE_SECTION_HEADER *sec; + IMAGE_SECTION_HEADER *sec = NULL; IMAGE_DATA_DIRECTORY *imports; NTSTATUS status = STATUS_CONFLICTING_ADDRESSES; int i; @@ -1130,7 +1130,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz sigset_t sigset; struct stat st; struct file_view *view = NULL; - char *ptr, *header_end; + char *ptr, *header_end, *header_start; INT_PTR delta = 0; /* zero-map the whole range */ @@ -1167,8 +1167,17 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz header_end = ptr + ROUND_SIZE( 0, header_size ); memset( ptr + header_size, 0, header_end - (ptr + header_size) ); if ((char *)(nt + 1) > header_end) goto error; - sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader); - if ((char *)(sec + nt->FileHeader.NumberOfSections) > header_end) goto error; + header_start = (char*)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader; + if (header_start + sizeof(*sec) * nt->FileHeader.NumberOfSections > header_end) goto error; + /* Some applications (e.g. the Steam version of Borderlands) map over the top of the section headers, + * copying the headers into local memory is necessary to properly load such applications. */ + sec = RtlAllocateHeap( virtual_heap, 0, sizeof(*sec) * nt->FileHeader.NumberOfSections); + if (!sec) + { + status = STATUS_NO_MEMORY; + goto error; + } + memcpy(sec, header_start, sizeof(*sec) * nt->FileHeader.NumberOfSections); imports = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT; if (!imports->Size || !imports->VirtualAddress) imports = NULL; @@ -1364,6 +1373,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz } done: + RtlFreeHeap( virtual_heap, 0, sec ); view->mapping = dup_mapping; view->map_protect = map_vprot; server_leave_uninterrupted_section( &csVirtual, &sigset ); @@ -1376,6 +1386,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz return STATUS_SUCCESS; error: + RtlFreeHeap( virtual_heap, 0, sec ); if (view) delete_view( view ); server_leave_uninterrupted_section( &csVirtual, &sigset ); if (dup_mapping) NtClose( dup_mapping ); -- 1.7.5.4