From 0fb2f3573cbe92216e7f56f2ac8b22e4427671ee Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Wed, 5 Apr 2017 21:08:32 +0300 Subject: [PATCH 02/32] Direct mapping of IL-assembly images that don't contain writeable sections. --- src/inc/pedecoder.h | 2 + src/utilcode/pedecoder.cpp | 31 ++++++++++++++++ src/vm/pefile.cpp | 15 +++++++- src/vm/peimage.cpp | 92 ++++++++++++++++++++++++++++++++++++++-------- src/vm/peimage.h | 2 +- 5 files changed, 124 insertions(+), 18 deletions(-) diff --git a/src/inc/pedecoder.h b/src/inc/pedecoder.h index d5bae87..01375e6 100644 --- a/src/inc/pedecoder.h +++ b/src/inc/pedecoder.h @@ -187,6 +187,8 @@ class PEDecoder DWORD GetImageIdentity() const; + BOOL HasWriteableSections() const; + // Directory entry access BOOL HasDirectoryEntry(int entry) const; diff --git a/src/utilcode/pedecoder.cpp b/src/utilcode/pedecoder.cpp index 3b3c937..babe374 100644 --- a/src/utilcode/pedecoder.cpp +++ b/src/utilcode/pedecoder.cpp @@ -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 diff --git a/src/vm/pefile.cpp b/src/vm/pefile.cpp index c7870e6..0c4f660 100644 --- a/src/vm/pefile.cpp +++ b/src/vm/pefile.cpp @@ -376,9 +376,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(); + } } } diff --git a/src/vm/peimage.cpp b/src/vm/peimage.cpp index 1462c94..bd5ad7f 100644 --- a/src/vm/peimage.cpp +++ b/src/vm/peimage.cpp @@ -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)); + } } } diff --git a/src/vm/peimage.h b/src/vm/peimage.h index f61e185..e77a474 100644 --- a/src/vm/peimage.h +++ b/src/vm/peimage.h @@ -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); -- 2.7.4