From 512c90efdbfdf9b0b1050d1eaa98f4aed1e8c165 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Sat, 23 Apr 2016 12:15:29 -0700 Subject: [PATCH] Fix loading of NI images on SELinux This change fixes a problem that prevents us to load crossgen-ed managed assemblies on SELinux when running in confined mode. The problem was that when we load these images, we also apply relocations to their sections and so we temporarily switch section protection from RX to RW and then back. And the switching back (RW -> RX) is something that SELinux doesn't allow. The fix is to switch to RWX before applying to relocations for sections that are RX, since it is allowed then to switch them back to RX. One more change was needed to get the original protection of the section before relocation so that we can set it back later. The PE files are not mapped using VirtualXXXX functions in the PAL and so VirtualProtect doesn't return the proper original protection, but a fixed value instead. So for PAL, we derive the original protection from the section attributes. --- src/vm/peimagelayout.cpp | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/vm/peimagelayout.cpp b/src/vm/peimagelayout.cpp index 80d2b87..b5d50b58 100644 --- a/src/vm/peimagelayout.cpp +++ b/src/vm/peimagelayout.cpp @@ -93,6 +93,40 @@ PEImageLayout* PEImageLayout::Map(HANDLE hFile, PEImage* pOwner) } #ifdef FEATURE_PREJIT + +#ifdef FEATURE_PAL +DWORD SectionCharacteristicsToPageProtection(UINT characteristics) +{ + _ASSERTE((characteristics & VAL32(IMAGE_SCN_MEM_READ)) != 0); + DWORD pageProtection; + + if ((characteristics & VAL32(IMAGE_SCN_MEM_WRITE)) != 0) + { + if ((characteristics & VAL32(IMAGE_SCN_MEM_EXECUTE)) != 0) + { + pageProtection = PAGE_EXECUTE_READWRITE; + } + else + { + pageProtection = PAGE_READWRITE; + } + } + else + { + if ((characteristics & VAL32(IMAGE_SCN_MEM_EXECUTE)) != 0) + { + pageProtection = PAGE_EXECUTE_READ; + } + else + { + pageProtection = PAGE_READONLY; + } + } + + return pageProtection; +} +#endif // FEATURE_PAL + //To force base relocation on Vista (which uses ASLR), unmask IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE //(0x40) for OptionalHeader.DllCharacteristics void PEImageLayout::ApplyBaseRelocations() @@ -154,9 +188,21 @@ void PEImageLayout::ApplyBaseRelocations() // Unprotect the section if it is not writable if (((pSection->Characteristics & VAL32(IMAGE_SCN_MEM_WRITE)) == 0)) { + DWORD dwNewProtection = PAGE_READWRITE; +#ifdef FEATURE_PAL + if (((pSection->Characteristics & VAL32(IMAGE_SCN_MEM_EXECUTE)) != 0)) + { + // On SELinux, we cannot change protection that doesn't have execute access rights + // to one that has it, so we need to set the protection to RWX instead of RW + dwNewProtection = PAGE_EXECUTE_READWRITE; + } +#endif // FEATURE_PAL if (!ClrVirtualProtect(pWriteableRegion, cbWriteableRegion, - PAGE_READWRITE, &dwOldProtection)) + dwNewProtection, &dwOldProtection)) ThrowLastError(); +#ifdef FEATURE_PAL + dwOldProtection = SectionCharacteristicsToPageProtection(pSection->Characteristics); +#endif // FEATURE_PAL } } -- 2.7.4