pkgsrc-WIP-changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

llvm-netbsd: extend Memory::allocateMappedMemory with PROT_MPROTECT



Module Name:	pkgsrc-wip
Committed By:	Kamil Rytarowski <n54%gmx.com@localhost>
Pushed By:	kamil
Date:		Fri Jul 28 19:41:36 2017 +0200
Changeset:	2c2c9c438c587f377019d3e69ca349e8f66304c6

Modified Files:
	llvm-netbsd/distinfo
Added Files:
	llvm-netbsd/patches/patch-include_llvm_Support_Memory.h
	llvm-netbsd/patches/patch-lib_Support_Unix_Memory.inc
	llvm-netbsd/patches/patch-unittests_Support_MemoryTest.cpp

Log Message:
llvm-netbsd: extend Memory::allocateMappedMemory with PROT_MPROTECT

This is fixes Memory usage on NetBSD and creates ground for JIT allocator.

Sponsored by <The NetBSD Foundation>

To see a diff of this commit:
https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commitdiff;h=2c2c9c438c587f377019d3e69ca349e8f66304c6

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

diffstat:
 llvm-netbsd/distinfo                               |  3 +
 .../patches/patch-include_llvm_Support_Memory.h    | 55 +++++++++++++++++
 .../patches/patch-lib_Support_Unix_Memory.inc      | 68 ++++++++++++++++++++++
 .../patches/patch-unittests_Support_MemoryTest.cpp | 63 ++++++++++++++++++++
 4 files changed, 189 insertions(+)

diffs:
diff --git a/llvm-netbsd/distinfo b/llvm-netbsd/distinfo
index 7931384fd5..57bf92733e 100644
--- a/llvm-netbsd/distinfo
+++ b/llvm-netbsd/distinfo
@@ -12,3 +12,6 @@ Size (libcxx-3.6.2.src.tar.xz) = 944020 bytes
 SHA1 (llvm-3.6.2.src.tar.xz) = 7a00257eb2bc9431e4c77c3a36b033072c54bc7e
 RMD160 (llvm-3.6.2.src.tar.xz) = 521cbc5fe2925ea3c6e90c7a31f752a04045c972
 Size (llvm-3.6.2.src.tar.xz) = 12802380 bytes
+SHA1 (patch-include_llvm_Support_Memory.h) = ba6eec99b1126ffbe27c18b63b3340697b192635
+SHA1 (patch-lib_Support_Unix_Memory.inc) = 69fc875b16e954e5fbf6fe2767d98c6f901713d4
+SHA1 (patch-unittests_Support_MemoryTest.cpp) = cd7bfc8053ceca839993e70e147cf803bac7eaae
diff --git a/llvm-netbsd/patches/patch-include_llvm_Support_Memory.h b/llvm-netbsd/patches/patch-include_llvm_Support_Memory.h
new file mode 100644
index 0000000000..1357346c9d
--- /dev/null
+++ b/llvm-netbsd/patches/patch-include_llvm_Support_Memory.h
@@ -0,0 +1,55 @@
+$NetBSD$
+
+--- include/llvm/Support/Memory.h.orig	2017-07-05 18:41:26.000000000 +0000
++++ include/llvm/Support/Memory.h
+@@ -36,6 +36,7 @@ namespace sys {
+   private:
+     void *Address;    ///< Address of first byte of memory area
+     size_t Size;      ///< Size, in bytes of the memory area
++    int MaxProtection;///< Maximum allowable Protection, of memory area
+     friend class Memory;
+   };
+ 
+@@ -61,16 +62,20 @@ namespace sys {
+     /// \p Flags is used to set the initial protection flags for the block
+     /// of the memory.
+     /// \p EC [out] returns an object describing any error that occurs.
++    /// \p MaxFlags is used to set the maximal protection flags for the block
++    /// of the memory. This value is OR'ed with \p Flags.
+     ///
+     /// This method may allocate more than the number of bytes requested.  The
+     /// actual number of bytes allocated is indicated in the returned
+     /// MemoryBlock.
+     ///
+     /// The start of the allocated block must be aligned with the
+-    /// system allocation granularity (64K on Windows, page size on Linux).
++    /// system allocation granularity (64K on Windows, page size on Linux, etc).
+     /// If the address following \p NearBlock is not so aligned, it will be
+     /// rounded up to the next allocation granularity boundary.
+     ///
++    /// For security reasons MF_WRITE | MF_EXEC mapping is prohibited.
++    ///
+     /// \r a non-null MemoryBlock if the function was successful,
+     /// otherwise a null MemoryBlock is with \p EC describing the error.
+     ///
+@@ -78,7 +83,7 @@ namespace sys {
+     static MemoryBlock allocateMappedMemory(size_t NumBytes,
+                                             const MemoryBlock *const NearBlock,
+                                             unsigned Flags,
+-                                            std::error_code &EC);
++                                            std::error_code &EC, unsigned MaxFlags = 0);
+ 
+     /// This method releases a block of memory that was allocated with the
+     /// allocateMappedMemory method. It should not be used to release any
+@@ -102,6 +107,11 @@ namespace sys {
+     /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the
+     /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386).
+     ///
++    /// The specified \p Flags parameter must by allowed by maximal protection
++    /// block of the memory.
++    ///
++    /// For security reasons MF_WRITE | MF_EXEC mapping is prohibited.
++    ///
+     /// \r error_success if the function was successful, or an error_code
+     /// describing the failure if an error occurred.
+     ///
diff --git a/llvm-netbsd/patches/patch-lib_Support_Unix_Memory.inc b/llvm-netbsd/patches/patch-lib_Support_Unix_Memory.inc
new file mode 100644
index 0000000000..a49693e9ea
--- /dev/null
+++ b/llvm-netbsd/patches/patch-lib_Support_Unix_Memory.inc
@@ -0,0 +1,68 @@
+$NetBSD$
+
+--- lib/Support/Unix/Memory.inc.orig	2017-07-05 18:38:14.000000000 +0000
++++ lib/Support/Unix/Memory.inc
+@@ -82,8 +82,16 @@ MemoryBlock
+ Memory::allocateMappedMemory(size_t NumBytes,
+                              const MemoryBlock *const NearBlock,
+                              unsigned PFlags,
+-                             std::error_code &EC) {
++                             std::error_code &EC,
++                             unsigned MaxPFlags) {
+   EC = std::error_code();
++
++  // W^X restriction
++  if ((PFlags & (MF_WRITE | MF_EXEC)) == (MF_WRITE | MF_EXEC)) {
++    EC = std::error_code(EACCES, std::generic_category());
++    return MemoryBlock();
++  }
++
+   if (NumBytes == 0)
+     return MemoryBlock();
+ 
+@@ -102,6 +110,13 @@ Memory::allocateMappedMemory(size_t NumB
+ 
+   int Protect = getPosixProtectionFlags(PFlags);
+ 
++  MaxPFlags |= PFlags;
++
++  // NetBSD with PaX MPROTECT must reserve additional allowable protection bits
++#if defined(__NetBSD__) && defined(PROT_MPROTECT)
++  Protect |= PROT_MPROTECT(getPosixProtectionFlags(MaxPFlags & (~PFlags)));
++#endif
++
+   // Use any near hint and the page size to set a page-aligned starting address
+   uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) +
+                                       NearBlock->size() : 0;
+@@ -112,7 +127,7 @@ Memory::allocateMappedMemory(size_t NumB
+                       Protect, MMFlags, fd, 0);
+   if (Addr == MAP_FAILED) {
+     if (NearBlock) //Try again without a near hint
+-      return allocateMappedMemory(NumBytes, nullptr, PFlags, EC);
++      return allocateMappedMemory(NumBytes, nullptr, PFlags, EC, MaxPFlags);
+ 
+     EC = std::error_code(errno, std::generic_category());
+     return MemoryBlock();
+@@ -121,6 +136,7 @@ Memory::allocateMappedMemory(size_t NumB
+   MemoryBlock Result;
+   Result.Address = Addr;
+   Result.Size = NumPages*PageSize;
++  Result.MaxProtection = MaxPFlags;
+ 
+   if (PFlags & MF_EXEC)
+     Memory::InvalidateInstructionCache(Result.Address, Result.Size);
+@@ -144,6 +160,14 @@ Memory::releaseMappedMemory(MemoryBlock 
+ 
+ std::error_code
+ Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) {
++  // W^X restriction
++  if ((Flags & (MF_WRITE | MF_EXEC)) == (MF_WRITE | MF_EXEC))
++    return std::error_code(EACCES, std::generic_category());
++
++  // Check whether new protection bits are allowed
++  if ((~M.MaxProtection) & Flags)
++    return std::error_code(EACCES, std::generic_category());
++
+   static const size_t PageSize = Process::getPageSize();
+   if (M.Address == nullptr || M.Size == 0)
+     return std::error_code();
diff --git a/llvm-netbsd/patches/patch-unittests_Support_MemoryTest.cpp b/llvm-netbsd/patches/patch-unittests_Support_MemoryTest.cpp
new file mode 100644
index 0000000000..c7ce025a70
--- /dev/null
+++ b/llvm-netbsd/patches/patch-unittests_Support_MemoryTest.cpp
@@ -0,0 +1,63 @@
+$NetBSD$
+
+--- unittests/Support/MemoryTest.cpp.orig	2017-07-05 18:41:47.000000000 +0000
++++ unittests/Support/MemoryTest.cpp
+@@ -33,9 +33,8 @@ protected:
+     case Memory::MF_READ|Memory::MF_WRITE:
+       return Memory::MF_READ|Memory::MF_WRITE;
+     case Memory::MF_READ|Memory::MF_EXEC:
+-    case Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC:
+     case Memory::MF_EXEC:
+-      return Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC;
++      return Memory::MF_READ|Memory::MF_EXEC;
+     }
+     // Default in case values are added to the enum, as required by some compilers
+     return Memory::MF_READ|Memory::MF_WRITE;
+@@ -181,14 +180,19 @@ TEST_P(MappedMemoryTest, MultipleWrite) 
+ 
+ TEST_P(MappedMemoryTest, EnabledWrite) {
+   std::error_code EC;
++
++  // W^R restriction
++  if (Flags & Memory::MF_EXEC)
++    return;
++
+   MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), nullptr, Flags,
+-                                                EC);
++                                                EC, getTestableEquivalent(Flags));
+   EXPECT_EQ(std::error_code(), EC);
+   MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags,
+-                                                EC);
++                                                EC, getTestableEquivalent(Flags));
+   EXPECT_EQ(std::error_code(), EC);
+   MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags,
+-                                                EC);
++                                                EC, getTestableEquivalent(Flags));
+   EXPECT_EQ(std::error_code(), EC);
+ 
+   EXPECT_NE((void*)nullptr, M1.base());
+@@ -223,7 +227,7 @@ TEST_P(MappedMemoryTest, EnabledWrite) {
+   EXPECT_FALSE(Memory::releaseMappedMemory(M3));
+   EXPECT_EQ(6, y[6]);
+ 
+-  MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
++  MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC, getTestableEquivalent(Flags));
+   EXPECT_EQ(std::error_code(), EC);
+   EXPECT_NE((void*)nullptr, M4.base());
+   EXPECT_LE(16U, M4.size());
+@@ -349,13 +353,13 @@ TEST_P(MappedMemoryTest, UnalignedNear) 
+ 
+ // Note that Memory::MF_WRITE is not supported exclusively across
+ // operating systems and architectures and can imply MF_READ|MF_WRITE
++// RWX mapping is not allowed (W^X restrictions)
+ unsigned MemoryFlags[] = {
+ 			   Memory::MF_READ,
+ 			   Memory::MF_WRITE,
+ 			   Memory::MF_READ|Memory::MF_WRITE,
+ 			   Memory::MF_EXEC,
+-			   Memory::MF_READ|Memory::MF_EXEC,
+-			   Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC
++			   Memory::MF_READ|Memory::MF_EXEC
+ 			 };
+ 
+ INSTANTIATE_TEST_CASE_P(AllocationTests,


Home | Main Index | Thread Index | Old Index