From: Bernhard Loos Subject: [PATCH 1/2] ntdll: windows refuses to load an image, if sections overlap the header size as given in the SizeOfHeaders field (try 2) Message-Id: Date: Wed, 12 Oct 2011 14:37:31 +0200 fixed a compiler warning --- dlls/kernel32/tests/loader.c | 79 ++++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/virtual.c | 5 +++ 2 files changed, 84 insertions(+), 0 deletions(-) diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index c740d77..a257695 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -692,9 +692,88 @@ static void test_section_access(void) } } +static void test_section_mapping(void) +{ + static const char filler[0x2000]; + static const char section_data[] = "section data 1234567890"; + DWORD total, written; + HANDLE hfile; + HMODULE hlib; + SYSTEM_INFO si; + char temp_path[MAX_PATH]; + char dll_name[MAX_PATH]; + BOOL ret; + + GetSystemInfo(&si); + + /* prevent displaying of the "Unable to load this DLL" message box */ + SetErrorMode(SEM_FAILCRITICALERRORS); + + GetTempPath(MAX_PATH, temp_path); + + GetTempFileName(temp_path, "ldr", 0, dll_name); + + /*trace("creating %s\n", dll_name);*/ + hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + if (hfile == INVALID_HANDLE_VALUE) + { + ok(0, "could not create %s\n", dll_name); + return; + } + + SetLastError(0xdeadbeef); + ret = WriteFile(hfile, &dos_header, sizeof(dos_header), &written, NULL); + ok(ret, "WriteFile error %d\n", GetLastError()); + total = written; + + nt_header.FileHeader.NumberOfSections = 1; + nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER); + + nt_header.OptionalHeader.SectionAlignment = si.dwPageSize; + nt_header.OptionalHeader.FileAlignment = 0x200; + nt_header.OptionalHeader.SizeOfImage = si.dwPageSize * 3; + nt_header.OptionalHeader.SizeOfHeaders = si.dwPageSize * 2; + SetLastError(0xdeadbeef); + ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &written, NULL); + ok(ret, "WriteFile error %d\n", GetLastError()); + total += written; + SetLastError(0xdeadbeef); + ret = WriteFile(hfile, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &written, NULL); + ok(ret, "WriteFile error %d\n", GetLastError()); + total += written; + + section.SizeOfRawData = sizeof(section_data); + section.PointerToRawData = nt_header.OptionalHeader.FileAlignment; + section.VirtualAddress = si.dwPageSize; + section.Misc.VirtualSize = section.SizeOfRawData; + SetLastError(0xdeadbeef); + ret = WriteFile(hfile, §ion, sizeof(section), &written, NULL); + ok(ret, "WriteFile error %d\n", GetLastError()); + total += written; + + assert(nt_header.OptionalHeader.SizeOfHeaders - total < sizeof(filler)); + SetLastError(0xdeadbeef); + ret = WriteFile(hfile, filler, nt_header.OptionalHeader.SizeOfHeaders - total, &written, NULL); + ok(ret, "WriteFile error %d\n", GetLastError()); + total += written; + + /* section data */ + SetLastError(0xdeadbeef); + ret = WriteFile(hfile, section_data, sizeof(section_data), &written, NULL); + ok(ret, "WriteFile error %d\n", GetLastError()); + total += written; + + CloseHandle(hfile); + + SetLastError(0xdeadbeef); + hlib = LoadLibrary(dll_name); + ok(hlib == 0 && GetLastError() == ERROR_BAD_EXE_FORMAT, "LoadLibrary succeded or wrong error: %d\n", GetLastError()); +} + START_TEST(loader) { test_Loader(); test_ImportDescriptors(); test_section_access(); + test_section_mapping(); } diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 5e69eb9..f17f9dc 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -1123,6 +1123,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 */ @@ -1160,6 +1161,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz 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; + SizeOfHeaders = ROUND_SIZE( 0, nt->OptionalHeader.SizeOfHeaders ); imports = nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT; if (!imports->Size || !imports->VirtualAddress) imports = NULL; @@ -1200,6 +1202,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