summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/inc/pedecoder.h2
-rw-r--r--src/utilcode/pedecoder.cpp31
-rw-r--r--src/vm/pefile.cpp15
-rw-r--r--src/vm/peimage.cpp92
-rw-r--r--src/vm/peimage.h2
5 files changed, 124 insertions, 18 deletions
diff --git a/src/inc/pedecoder.h b/src/inc/pedecoder.h
index d5bae87bb7..01375e6d88 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 3b3c937419..babe374542 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 b54301f80a..5d908c5cb4 100644
--- a/src/vm/pefile.cpp
+++ b/src/vm/pefile.cpp
@@ -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();
+ }
}
}
diff --git a/src/vm/peimage.cpp b/src/vm/peimage.cpp
index 1462c94f51..bd5ad7f27c 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 f61e185ad6..e77a474c2d 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);