[PATCH] D33874: Implement AllocateRWX and ReleaseRWX for NetBSD

Kamil Rytarowski via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 3 16:31:17 PDT 2017


krytarowski created this revision.
Herald added a subscriber: arichardson.

NetBSD ships with PaX MPROTECT disallowing RWX mappings.
There is a solution to bypass this restriction with double mapping
RX (code0 and RW (data) using mremap(2) MAP_REMAPDUP.
The initial mapping must be mmap(2)ed with protection:
PROT_MPROTECT(PROT_EXEC).

This functionality to bypass PaX MPROTECT appeared in NetBSD-7.99.72.

This patch fixes 20 failing tests:

- LLVM :: DebugInfo/debuglineinfo-macho.test
- LLVM :: DebugInfo/debuglineinfo.test
- LLVM :: ExecutionEngine/RuntimeDyld/Mips/ELF_Mips64r2N64_PIC_relocations.s
- LLVM :: ExecutionEngine/RuntimeDyld/Mips/ELF_N32_relocations.s
- LLVM :: ExecutionEngine/RuntimeDyld/Mips/ELF_N64R6_relocations.s
- LLVM :: ExecutionEngine/RuntimeDyld/Mips/ELF_O32R6_relocations.s
- LLVM :: ExecutionEngine/RuntimeDyld/Mips/ELF_O32_PIC_relocations.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/COFF_i386.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/COFF_x86_64.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/ELF-relaxed.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/ELF_STT_FILE.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/ELF_x64-64_PC8_relocations.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/ELF_x64-64_PIC_relocations.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/ELF_x86-64_PIC-small-relocations.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/ELF_x86-64_debug_frame.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/ELF_x86_64_StubBuf.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/MachO_empty_ehframe.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/MachO_i386_DynNoPIC_relocations.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/MachO_i386_eh_frame.s
- LLVM :: ExecutionEngine/RuntimeDyld/X86/MachO_x86-64_PIC_relocations.s

Sponsored by <The NetBSD Foundation>


Repository:
  rL LLVM

https://reviews.llvm.org/D33874

Files:
  lib/Support/Unix/Memory.inc


Index: lib/Support/Unix/Memory.inc
===================================================================
--- lib/Support/Unix/Memory.inc
+++ lib/Support/Unix/Memory.inc
@@ -177,7 +177,16 @@
   if (NumBytes == 0) return MemoryBlock();
 
   static const size_t PageSize = Process::getPageSize();
-  size_t NumPages = (NumBytes+PageSize-1)/PageSize;
+
+  static const size_t overhead =
+#if __NetBSD_Version__ - 0 >= 799007200
+      sizeof(void*)
+#else
+      0
+#endif
+      ;
+
+  size_t NumPages = (NumBytes + overhead + PageSize - 1) / PageSize;
 
   int fd = -1;
 
@@ -195,6 +204,10 @@
 #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
   void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_EXEC,
                     flags, fd, 0);
+#elif __NetBSD_Version__ - 0 >= 799007200
+  void *pa =
+      ::mmap(start, PageSize * NumPages,
+             PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC), flags, fd, 0);
 #else
   void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
                     flags, fd, 0);
@@ -223,19 +236,51 @@
     MakeErrMsg(ErrMsg, "vm_protect RW failed");
     return MemoryBlock();
   }
+#elif __NetBSD_Version__ - 0 >= 799007200
+  void *codeseg =
+      mremap(pa, PageSize * NumPages, NULL, PageSize * NumPages, MAP_REMAPDUP);
+  if (codeseg == MAP_FAILED) {
+    munmap(pa, PageSize * NumPages);
+
+    if (NearBlock) // Try again without a near hint
+      return AllocateRWX(NumBytes, nullptr);
+
+    MakeErrMsg(ErrMsg, "Can't allocate RWX Memory");
+    return MemoryBlock();
+  }
+  if (mprotect(codeseg, PageSize * NumPages, PROT_READ | PROT_EXEC) == -1) {
+    munmap(pa, PageSize * NumPages);
+    munmap(codeseg, PageSize * NumPages);
+    if (NearBlock) // Try again without a near hint
+      return AllocateRWX(NumBytes, nullptr);
+
+    MakeErrMsg(ErrMsg, "Can't allocate RWX Memory");
+    return MemoryBlock();
+  }
+  // Rembember code segment pointer, to be able to free it later
+  memcpy(pa, &codeseg, sizeof(void *));
 #endif
 
   MemoryBlock result;
-  result.Address = pa;
-  result.Size = NumPages*PageSize;
+  result.Address = (void *)((uintptr_t)pa + overhead);
+  result.Size = NumPages*PageSize - overhead;
 
   return result;
 }
 
 bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) {
   if (M.Address == nullptr || M.Size == 0) return false;
+#if __NetBSD_Version__ - 0 >= 799007200
+  static const size_t overhead = sizeof(void *);
+  void *codeseg;
+  memcpy(&codeseg, (void *)((uintptr_t)M.Address - overhead), sizeof(void *));
+  if (0 != ::munmap(codeseg, M.Size + overhead) ||
+      0 != ::munmap(M.Address, M.Size + overhead))
+    return MakeErrMsg(ErrMsg, "Can't release RWX Memory");
+#else
   if (0 != ::munmap(M.Address, M.Size))
     return MakeErrMsg(ErrMsg, "Can't release RWX Memory");
+#endif
   return false;
 }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D33874.101337.patch
Type: text/x-patch
Size: 2854 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170603/85fe595c/attachment.bin>


More information about the llvm-commits mailing list