[PATCH v2] ntdll: Fix overflow if running 32bit app w/ wine64
Brendan McGrath
brendan at redmandi.com
Wed Oct 24 16:42:24 CDT 2018
Did you mean something like the below? This also fixes my test case -
but I feel like my original patch was a lot safer (obviously the
'imports' reference should be fixed regardless).
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index af1509eae5d..9be494ba57f 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -1364,7 +1364,7 @@ static NTSTATUS map_image( HANDLE hmapping,
ACCESS_MASK access, int fd, SIZE_T m
IMAGE_NT_HEADERS *nt;
IMAGE_SECTION_HEADER sections[96];
IMAGE_SECTION_HEADER *sec;
- IMAGE_DATA_DIRECTORY *imports;
+ IMAGE_DATA_DIRECTORY *imports = NULL;
NTSTATUS status = STATUS_CONFLICTING_ADDRESSES;
SIZE_T header_size, total_size = image_info->map_size;
int i;
@@ -1423,7 +1423,47 @@ static NTSTATUS map_image( HANDLE hmapping,
ACCESS_MASK access, int fd, SIZE_T m
memcpy(sections, header_start, sizeof(*sections) *
nt->FileHeader.NumberOfSections);
sec = sections;
- imports = nt->OptionalHeader.DataDirectory +
IMAGE_DIRECTORY_ENTRY_IMPORT;
+ if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC &&
is_win64 &&
+ !(nt->FileHeader.Characteristics & IMAGE_FILE_DLL)) {
+ IMAGE_OPTIONAL_HEADER32 *hdr32 = (IMAGE_OPTIONAL_HEADER32 *)
&nt->OptionalHeader;
+ /* check if there is room in the header for generating a PE64
header,
+ * if not - we'll leave it and hope for the best */
+ if (header_start + sizeof(IMAGE_OPTIONAL_HEADER64) -
sizeof(IMAGE_OPTIONAL_HEADER32)
+ + sizeof(*sections) *
nt->FileHeader.NumberOfSections <= header_end) {
+ /* We'll convert the IMAGE_OPTIONAL_HEADER32 to
IMAGE_OPTIONAL_HEADER64
+ * we'll splat the sections area - but this was just copied.
+ * we copy from back to front so we don't splat the data we
still need */
+ memmove(nt->OptionalHeader.DataDirectory, hdr32->DataDirectory,
+ hdr32->NumberOfRvaAndSizes *
sizeof(hdr32->DataDirectory[0]));
+ nt->OptionalHeader.NumberOfRvaAndSizes =
hdr32->NumberOfRvaAndSizes;
+ nt->OptionalHeader.LoaderFlags = hdr32->LoaderFlags;
+ nt->OptionalHeader.SizeOfHeapCommit = hdr32->SizeOfHeapCommit;
+ nt->OptionalHeader.SizeOfHeapReserve = hdr32->SizeOfHeapReserve;
+ nt->OptionalHeader.SizeOfStackCommit = hdr32->SizeOfStackCommit;
+ nt->OptionalHeader.SizeOfStackReserve =
hdr32->SizeOfStackReserve;
+ nt->OptionalHeader.ImageBase = hdr32->ImageBase;
+ /* the rest of the values align between the 32bit and 64bit
optional header */
+
+ /* update the magic value and the size of optional header */
+ nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ nt->FileHeader.SizeOfOptionalHeader +=
sizeof(IMAGE_OPTIONAL_HEADER64)
+ -
sizeof(IMAGE_OPTIONAL_HEADER32);
+
+ /* copy the sections back
+ * Will this will break apps that map over the top of the
section headers?
+ * (hopefully none of these are 32bit .NET/Mono apps anyway) */
+ memcpy((char*)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader,
+ sections, sizeof(*sections) *
nt->FileHeader.NumberOfSections);
+ } else {
+ /* even though we can't create a PE64 header, we can still
make sure
+ * imports points to the correct location */
+ imports = hdr32->DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT;
+ }
+ }
+
+ if (!imports)
+ imports = nt->OptionalHeader.DataDirectory +
IMAGE_DIRECTORY_ENTRY_IMPORT;
+
if (!imports->Size || !imports->VirtualAddress) imports = NULL;
/* check for non page-aligned binary */
On 19/10/18 5:32 am, Alexandre Julliard wrote:
> Brendan McGrath <brendan at redmandi.com> writes:
>
>> But if you run:
>> wine64 mono32
>>
>> you get the Out of Memory error that is fixed by this patch. Applying
>> this patch allows these applications to work as they currently do
>> under Windows.
> For .NET binaries this should be solved by generating a PE64 header to
> replace the PE32 one.
>
More information about the wine-devel
mailing list