Hi,

Currently LoadLibrary is called on the file that is possibly a CLI image. This patch adds a check to ensure that the image is really a CLI image before calling LoadLibrary.

_CorValidateImage is only called for CLI images so this extra check is required to ensure security.

Please review and approve the patch.

Thanks.

Kornél
Index: mono/mono/metadata/image.c
===================================================================
--- mono/mono/metadata/image.c  (revision 106858)
+++ mono/mono/metadata/image.c  (working copy)
@@ -1130,7 +1130,7 @@
                                /* Increment reference count on images loaded 
outside of the runtime. */
                                fname_utf16 = g_utf8_to_utf16 (absfname, -1, 
NULL, NULL, NULL);
                                module_handle = LoadLibrary (fname_utf16);
-                               g_assert (module_handle != NULL);
+                               g_assert (module_handle == (HMODULE) 
image->raw_data);
                        }
                        mono_image_addref (image);
                        mono_images_unlock ();
@@ -1141,7 +1141,7 @@
                }
 
                fname_utf16 = g_utf8_to_utf16 (absfname, -1, NULL, NULL, NULL);
-               module_handle = LoadLibrary (fname_utf16);
+               module_handle = MonoLoadImage (fname_utf16);
                if (status && module_handle == NULL)
                        last_error = GetLastError ();
 
Index: mono/mono/metadata/coree.c
===================================================================
--- mono/mono/metadata/coree.c  (revision 106858)
+++ mono/mono/metadata/coree.c  (working copy)
@@ -301,8 +301,8 @@
        
NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress
 = 
NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
        
NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size 
= 
NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
        
NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress
 = 
NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
-       
NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size 
= 0;
-       
NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress
 = 0;
+       
NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size 
= 
NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
+       
NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress
 = 
NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
        
NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size 
= 0;
        
NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress
 = 0;
        
NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size 
= 
NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size;
@@ -344,6 +344,9 @@
        if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
                return STATUS_INVALID_IMAGE_FORMAT;
 
+       if (NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= 
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)
+               return STATUS_INVALID_IMAGE_FORMAT;
+
        CliHeaderDir = 
&NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
        if (!CliHeaderDir->VirtualAddress)
                return STATUS_INVALID_IMAGE_FORMAT;
@@ -382,6 +385,79 @@
        return CorBindToRuntimeEx (pwszVersion, pwszBuildFlavor, 0, rclsid, 
riid, ppv);
 }
 
+HMODULE WINAPI MonoLoadImage(LPCWSTR FileName)
+{
+       HANDLE FileHandle;
+       DWORD FileSize;
+       HANDLE MapHandle;
+       IMAGE_DOS_HEADER* DosHeader;
+       IMAGE_NT_HEADERS32* NtHeaders32;
+       IMAGE_NT_HEADERS64* NtHeaders64;
+       HMODULE ModuleHandle;
+
+       FileHandle = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, 
OPEN_EXISTING, 0, NULL);
+       if (FileHandle == INVALID_HANDLE_VALUE)
+               return NULL;
+
+       FileSize = GetFileSize(FileHandle, NULL); 
+       if (FileSize == INVALID_FILE_SIZE)
+               goto CloseFile;
+
+       MapHandle = CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, 
NULL);
+       if (MapHandle == NULL)
+               goto CloseFile;
+
+       DosHeader = (IMAGE_DOS_HEADER*)MapViewOfFile(MapHandle, FILE_MAP_READ, 
0, 0, 0);
+       if (DosHeader == NULL)
+               goto CloseMap;
+
+       if (FileSize < sizeof(IMAGE_DOS_HEADER) || DosHeader->e_magic != 
IMAGE_DOS_SIGNATURE || FileSize < DosHeader->e_lfanew + 
sizeof(IMAGE_NT_HEADERS32))
+               goto InvalidImageFormat;
+
+       NtHeaders32 = (IMAGE_NT_HEADERS32*)((DWORD_PTR)DosHeader + 
DosHeader->e_lfanew);
+       if (NtHeaders32->Signature != IMAGE_NT_SIGNATURE)
+               goto InvalidImageFormat;
+
+#ifdef _WIN64
+       NtHeaders64 = (IMAGE_NT_HEADERS64*)NtHeaders32;
+       if (NtHeaders64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+       {
+               if (FileSize < DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS64) 
||
+                       NtHeaders64->OptionalHeader.NumberOfRvaAndSizes <= 
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ||
+                       
!NtHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress)
+                               goto InvalidImageFormat;
+
+               goto ValidImage;
+       }
+#endif
+
+       if (NtHeaders32->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC 
||
+               NtHeaders32->OptionalHeader.NumberOfRvaAndSizes <= 
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ||
+               
!NtHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress)
+       {
+InvalidImageFormat:
+               SetLastError(STATUS_INVALID_IMAGE_FORMAT);
+               goto UnmapView;
+       }
+
+ValidImage:
+       UnmapViewOfFile(DosHeader);
+       CloseHandle(MapHandle);
+
+       ModuleHandle = LoadLibrary(FileName);
+
+       CloseHandle(FileHandle);
+       return ModuleHandle;
+
+UnmapView:
+       UnmapViewOfFile(DosHeader);
+CloseMap:
+       CloseHandle(MapHandle);
+CloseFile:
+       CloseHandle(FileHandle);
+       return NULL;
+}
+
 typedef struct _EXPORT_FIXUP
 {
        LPCSTR Name;
Index: mono/mono/metadata/coree.h
===================================================================
--- mono/mono/metadata/coree.h  (revision 106858)
+++ mono/mono/metadata/coree.h  (working copy)
@@ -28,6 +28,8 @@
 
 extern HMODULE coree_module_handle MONO_INTERNAL;
 
+HMODULE WINAPI MonoLoadImage(LPCWSTR FileName) MONO_INTERNAL;
+
 gchar* mono_get_module_file_name (HMODULE module_handle) MONO_INTERNAL;
 void mono_load_coree (const char* file_name) MONO_INTERNAL;
 void mono_fixup_exe_image (MonoImage* image) MONO_INTERNAL;
_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to