Direct mapping of IL-assembly images that don't contain writeable sections.
authorRuben Ayrapetyan <r.ayrapetyan@samsung.com>
Wed, 5 Apr 2017 18:08:32 +0000 (21:08 +0300)
committerJan Kotas <jkotas@microsoft.com>
Tue, 23 May 2017 14:54:50 +0000 (07:54 -0700)
src/inc/pedecoder.h
src/utilcode/pedecoder.cpp
src/vm/pefile.cpp
src/vm/peimage.cpp
src/vm/peimage.h

index d5bae87..01375e6 100644 (file)
@@ -187,6 +187,8 @@ class PEDecoder
 
     DWORD GetImageIdentity() const;
 
+    BOOL HasWriteableSections() const;
+
     // Directory entry access
 
     BOOL HasDirectoryEntry(int entry) const;
index 3b3c937..babe374 100644 (file)
@@ -440,6 +440,37 @@ CHECK PEDecoder::CheckSection(COUNT_T previousAddressEnd, COUNT_T addressStart,
     CHECK_OK;
 }
 
+BOOL PEDecoder::HasWriteableSections() const
+{
+    CONTRACT_CHECK
+    {
+        INSTANCE_CHECK;
+        PRECONDITION(CheckFormat());
+        NOTHROW;
+        GC_NOTRIGGER;
+        SUPPORTS_DAC;
+        SO_TOLERANT;
+    }
+    CONTRACT_CHECK_END;
+
+    PTR_IMAGE_SECTION_HEADER pSection = FindFirstSection(FindNTHeaders());
+    _ASSERTE(pSection != NULL);
+
+    PTR_IMAGE_SECTION_HEADER pSectionEnd = pSection + VAL16(FindNTHeaders()->FileHeader.NumberOfSections);
+
+    while (pSection < pSectionEnd)
+    {
+        if ((pSection->Characteristics & VAL32(IMAGE_SCN_MEM_WRITE)) != 0)
+        {
+            return TRUE;
+        }
+
+        pSection++;
+    }
+
+    return FALSE;
+}
+
 CHECK PEDecoder::CheckDirectoryEntry(int entry, int forbiddenFlags, IsNullOK ok) const
 {
     CONTRACT_CHECK
index b54301f..5d908c5 100644 (file)
@@ -354,9 +354,22 @@ void PEFile::LoadLibrary(BOOL allowNativeSkip/*=TRUE*/) // if allowNativeSkip==F
 #endif
         {
             if (GetILimage()->IsFile())
-                GetILimage()->LoadFromMapped();
+            {
+#ifdef PLATFORM_UNIX
+                if (GetILimage()->IsILOnly())
+                {
+                    GetILimage()->Load();
+                }
+                else
+#endif // PLATFORM_UNIX
+                {
+                    GetILimage()->LoadFromMapped();
+                }
+            }
             else
+            {
                 GetILimage()->LoadNoFile();
+            }
         }
     }
 
index 1462c94..bd5ad7f 100644 (file)
@@ -909,13 +909,36 @@ PTR_PEImageLayout PEImage::GetLayoutInternal(DWORD imageLayoutMask,DWORD flags)
     {
         _ASSERTE(HasID());
 
-        if (imageLayoutMask&PEImageLayout::LAYOUT_MAPPED)
+        BOOL bIsMappedLayoutSuitable = ((imageLayoutMask & PEImageLayout::LAYOUT_MAPPED) != 0);
+        BOOL bIsFlatLayoutSuitable = ((imageLayoutMask & PEImageLayout::LAYOUT_FLAT) != 0);
+
+#if !defined(PLATFORM_UNIX)
+        if (bIsMappedLayoutSuitable)
         {
-          pRetVal = PEImage::CreateLayoutMapped();
+            bIsFlatLayoutSuitable = FALSE;
         }
-        else
+#endif // !PLATFORM_UNIX
+
+        _ASSERTE(bIsMappedLayoutSuitable || bIsFlatLayoutSuitable);
+
+        BOOL bIsMappedLayoutRequired = !bIsFlatLayoutSuitable;
+        BOOL bIsFlatLayoutRequired = !bIsMappedLayoutSuitable;
+
+        if (bIsFlatLayoutRequired
+            || (bIsFlatLayoutSuitable && !m_bIsTrustedNativeImage))
         {
-          pRetVal = PEImage::CreateLayoutFlat();
+          _ASSERTE(bIsFlatLayoutSuitable);
+
+          BOOL bPermitWriteableSections = bIsFlatLayoutRequired;
+
+          pRetVal = PEImage::CreateLayoutFlat(bPermitWriteableSections);
+        }
+
+        if (pRetVal == NULL)
+        {
+          _ASSERTE(bIsMappedLayoutSuitable);
+
+          pRetVal = PEImage::CreateLayoutMapped();
         }
     }
 
@@ -992,7 +1015,7 @@ PTR_PEImageLayout PEImage::CreateLayoutMapped()
     return pRetVal;
 }
 
-PTR_PEImageLayout PEImage::CreateLayoutFlat()
+PTR_PEImageLayout PEImage::CreateLayoutFlat(BOOL bPermitWriteableSections)
 {
     CONTRACTL
     {
@@ -1002,12 +1025,22 @@ PTR_PEImageLayout PEImage::CreateLayoutFlat()
     }
     CONTRACTL_END;
 
-    PTR_PEImageLayout pRetVal;
+    _ASSERTE(m_pLayouts[IMAGE_FLAT] == NULL);
 
-    pRetVal = PEImageLayout::LoadFlat(GetFileHandle(),this);
-    m_pLayouts[IMAGE_FLAT] = pRetVal;
+    PTR_PEImageLayout pFlatLayout = PEImageLayout::LoadFlat(GetFileHandle(),this);
 
-    return pRetVal;
+    if (!bPermitWriteableSections && pFlatLayout->HasWriteableSections())
+    {
+        pFlatLayout->Release();
+
+        return NULL;
+    }
+    else
+    {
+        m_pLayouts[IMAGE_FLAT] = pFlatLayout;
+
+        return pFlatLayout;
+    }
 }
 
 /* static */
@@ -1070,17 +1103,44 @@ void PEImage::Load()
     }
 
     SimpleWriteLockHolder lock(m_pLayoutLock);
-    if(!IsFile())
+
+    _ASSERTE(m_pLayouts[IMAGE_LOADED] == NULL);
+
+#ifdef PLATFORM_UNIX
+    if (m_pLayouts[IMAGE_FLAT] != NULL
+        && m_pLayouts[IMAGE_FLAT]->CheckFormat()
+        && m_pLayouts[IMAGE_FLAT]->IsILOnly()
+        && !m_pLayouts[IMAGE_FLAT]->HasWriteableSections())
     {
-        if (!m_pLayouts[IMAGE_FLAT]->CheckILOnly())
-            ThrowHR(COR_E_BADIMAGEFORMAT);
-        if(m_pLayouts[IMAGE_LOADED]==NULL)
-            SetLayout(IMAGE_LOADED,PEImageLayout::LoadFromFlat(m_pLayouts[IMAGE_FLAT]));
+        // IL-only images with writeable sections are mapped in general way,
+        // because the writeable sections should always be page-aligned
+        // to make possible setting another protection bits exactly for these sections
+        _ASSERTE(!m_pLayouts[IMAGE_FLAT]->HasWriteableSections());
+
+        // As the image is IL-only, there should no be native code to execute
+        _ASSERTE(!m_pLayouts[IMAGE_FLAT]->HasNativeEntryPoint());
+
+        m_pLayouts[IMAGE_FLAT]->AddRef();
+
+        SetLayout(IMAGE_LOADED, m_pLayouts[IMAGE_FLAT]);
     }
     else
+#endif // PLATFORM_UNIX
     {
-        if(m_pLayouts[IMAGE_LOADED]==NULL)
-            SetLayout(IMAGE_LOADED,PEImageLayout::Load(this,TRUE));
+        if(!IsFile())
+        {
+            _ASSERTE(m_pLayouts[IMAGE_FLAT] != NULL);
+
+            if (!m_pLayouts[IMAGE_FLAT]->CheckILOnly())
+                ThrowHR(COR_E_BADIMAGEFORMAT);
+            if(m_pLayouts[IMAGE_LOADED]==NULL)
+                SetLayout(IMAGE_LOADED,PEImageLayout::LoadFromFlat(m_pLayouts[IMAGE_FLAT]));
+        }
+        else
+        {
+            if(m_pLayouts[IMAGE_LOADED]==NULL)
+                SetLayout(IMAGE_LOADED,PEImageLayout::Load(this,TRUE));
+        }
     }
 }
 
index f61e185..e77a474 100644 (file)
@@ -262,7 +262,7 @@ private:
     PTR_PEImageLayout CreateLayoutMapped();
 
     // Create the flat layout
-    PTR_PEImageLayout CreateLayoutFlat();
+    PTR_PEImageLayout CreateLayoutFlat(BOOL bPermitWriteableSections);
 #endif
     // Get an existing layout corresponding to the mask, no AddRef
     PTR_PEImageLayout GetExistingLayoutInternal(DWORD imageLayoutMask);