On Mon, Oct 10, 2011 at 11:36:33AM +0200, Bernhard Loos wrote:
dlls/ntdll/virtual.c | 38 ++++++++++++++++++++++++++++++++++---- 1 files changed, 34 insertions(+), 4 deletions(-)
I think this needs tests, the algorithms are very fragile.
Ciao, Marcus
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 5e69eb9..7841d9c 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -1114,6 +1114,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 *section_table = NULL; IMAGE_DATA_DIRECTORY *imports; NTSTATUS status = STATUS_CONFLICTING_ADDRESSES; int i;
@@ -1123,6 +1124,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz struct file_view *view = NULL; char *ptr, *header_end; INT_PTR delta = 0;
DWORD SizeOfHeaders;
/* zero-map the whole range */
@@ -1158,8 +1160,11 @@ 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;
section_table = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
/* make sure we mapped enough memory */
if ((char *)(section_table + nt->FileHeader.NumberOfSections) > header_end) goto error;
/* windows is only interested in the size as given by OptionalHeader.SizeOfHeaders */
SizeOfHeaders = ROUND_SIZE( 0, nt->OptionalHeader.SizeOfHeaders );
imports = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT; if (!imports->Size || !imports->VirtualAddress) imports = NULL;
@@ -1180,7 +1185,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz if (nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) goto error; for (i = 0; i < nt->FileHeader.NumberOfSections; i++) {
if (sec[i].VirtualAddress != sec[i].PointerToRawData)
if (section_table[i].VirtualAddress != section_table[i].PointerToRawData) goto error; /* Windows refuses to load in that case too */ }
@@ -1192,6 +1197,24 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz goto done; }
if ((char *)(section_table + nt->FileHeader.NumberOfSections) > ptr + SizeOfHeaders)
{
/* part of the section table is outside of SizeOfHeaders
* at this point, it's likely that a section will get mapped over
* the section table (Borderlands does this)
* Not sure how it works on Windows, but we make a copy of the
* table at this point */
sec = RtlAllocateHeap( virtual_heap, 0, sizeof(*sec) * nt->FileHeader.NumberOfSections);
if (!sec)
{
status = STATUS_NO_MEMORY;
goto error;
}
memcpy( sec, section_table, sizeof(*sec) * nt->FileHeader.NumberOfSections);
section_table = sec;
}
else
sec = section_table;
/* map all the sections */
@@ -1200,6 +1223,9 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz static const SIZE_T sector_align = 0x1ff; SIZE_T map_size, file_start, file_size, end;
if (sec->VirtualAddress < SizeOfHeaders)
goto error;
if (!sec->Misc.VirtualSize) map_size = ROUND_SIZE( 0, sec->SizeOfRawData ); else
@@ -1329,7 +1355,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz
VIRTUAL_SetProt( view, ptr, ROUND_SIZE( 0, header_size ), VPROT_COMMITTED | VPROT_READ );
- sec = (IMAGE_SECTION_HEADER*)((char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
- sec = section_table; for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++) { SIZE_T size;
@@ -1361,6 +1387,8 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz }
done:
- if (section_table && (char *)section_table != (char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader)
view->mapping = dup_mapping; server_leave_uninterrupted_section( &csVirtual, &sigset );RtlFreeHeap( virtual_heap, 0, section_table );
@@ -1373,6 +1401,8 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz
error: if (view) delete_view( view );
- if (section_table && (char *)section_table != (char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader)
server_leave_uninterrupted_section( &csVirtual, &sigset ); if (dup_mapping) NtClose( dup_mapping ); return status;RtlFreeHeap( virtual_heap, 0, section_table );