[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