patch-rpython_rlib_rmmap_py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. $OpenBSD: patch-rpython_rlib_rmmap_py,v 1.1 2016/08/15 09:16:40 edd Exp $
  2. Make the CPython bootstrap W^X compatible.
  3. --- rpython/rlib/rmmap.py.orig Tue Jun 14 08:46:04 2016
  4. +++ rpython/rlib/rmmap.py Thu Aug 11 08:49:22 2016
  5. @@ -155,6 +155,9 @@ if _POSIX:
  6. c_mremap, _ = external('mremap',
  7. [PTR, size_t, size_t, rffi.ULONG], PTR)
  8. + c_mprotect, _ = external('mprotect',
  9. + [PTR, size_t, rffi.INT], rffi.INT)
  10. +
  11. # this one is always safe
  12. _pagesize = rffi_platform.getintegerfunctionresult('getpagesize',
  13. includes=includes)
  14. @@ -694,11 +697,29 @@ if _POSIX:
  15. def alloc_hinted(hintp, map_size):
  16. flags = MAP_PRIVATE | MAP_ANONYMOUS
  17. prot = PROT_EXEC | PROT_READ | PROT_WRITE
  18. +
  19. if we_are_translated():
  20. flags = NonConstant(flags)
  21. prot = NonConstant(prot)
  22. return c_mmap_safe(hintp, map_size, prot, flags, -1, 0)
  23. + def alloc_hinted_noexec(hintp, map_size):
  24. + """Same as alloc_hinted, but allocates pages non-executable.
  25. + Duplicated because of constancy constraints on prot."""
  26. +
  27. + flags = MAP_PRIVATE | MAP_ANONYMOUS
  28. + prot = PROT_READ | PROT_WRITE
  29. +
  30. + if we_are_translated():
  31. + flags = NonConstant(flags)
  32. + prot = NonConstant(prot)
  33. + return c_mmap_safe(hintp, map_size, prot, flags, -1, 0)
  34. +
  35. + def set_pages_executable(addr, size):
  36. + rv = c_mprotect(addr, size, PROT_EXEC)
  37. + if rv < 0:
  38. + debug.fatalerror_notb("set_pages_executable failed")
  39. +
  40. def clear_large_memory_chunk_aligned(addr, map_size):
  41. addr = rffi.cast(PTR, addr)
  42. flags = MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS
  43. @@ -714,10 +735,10 @@ if _POSIX:
  44. pos = -0x4fff0000 # for reproducible results
  45. hint = Hint()
  46. - def alloc(map_size):
  47. + def alloc(map_size, no_exec=False):
  48. """Allocate memory. This is intended to be used by the JIT,
  49. - so the memory has the executable bit set and gets allocated
  50. - internally in case of a sandboxed process.
  51. + so the memory has the executable bit set (unless no_exec=True)
  52. + and gets allocated internally in case of a sandboxed process.
  53. """
  54. from errno import ENOMEM
  55. from rpython.rlib import debug
  56. @@ -730,11 +751,17 @@ if _POSIX:
  57. if res == rffi.cast(PTR, 0):
  58. raise MemoryError
  59. return res
  60. - res = alloc_hinted(rffi.cast(PTR, hint.pos), map_size)
  61. + if no_exec:
  62. + res = alloc_hinted_noexec(rffi.cast(PTR, hint.pos), map_size)
  63. + else:
  64. + res = alloc_hinted(rffi.cast(PTR, hint.pos), map_size)
  65. if res == rffi.cast(PTR, -1):
  66. # some systems (some versions of OS/X?) complain if they
  67. # are passed a non-zero address. Try again.
  68. - res = alloc_hinted(rffi.cast(PTR, 0), map_size)
  69. + if no_exec:
  70. + res = alloc_hinted_noexec(rffi.cast(PTR, 0), map_size)
  71. + else:
  72. + res = alloc_hinted(rffi.cast(PTR, 0), map_size)
  73. if res == rffi.cast(PTR, -1):
  74. # ENOMEM simply raises MemoryError, but other errors are fatal
  75. if rposix.get_saved_errno() != ENOMEM:
  76. @@ -748,7 +775,7 @@ if _POSIX:
  77. else:
  78. hint.pos += map_size
  79. return res
  80. - alloc._annenforceargs_ = (int,)
  81. + alloc._annenforceargs_ = (int, bool)
  82. if _CYGWIN:
  83. free = c_free_safe
  84. @@ -886,11 +913,13 @@ elif _MS_WINDOWS:
  85. hint = Hint()
  86. # XXX this has no effect on windows
  87. - def alloc(map_size):
  88. + def alloc(map_size, no_exec=False):
  89. """Allocate memory. This is intended to be used by the JIT,
  90. so the memory has the executable bit set.
  91. XXX implement me: it should get allocated internally in
  92. case of a sandboxed process
  93. +
  94. + XXX no_exec ignored on windows.
  95. """
  96. null = lltype.nullptr(rffi.VOIDP.TO)
  97. res = VirtualAlloc_safe(null, map_size, MEM_COMMIT | MEM_RESERVE,
  98. @@ -902,7 +931,7 @@ elif _MS_WINDOWS:
  99. lltype.free(arg, flavor='raw')
  100. # ignore errors, just try
  101. return res
  102. - alloc._annenforceargs_ = (int,)
  103. + alloc._annenforceargs_ = (int, bool)
  104. def free(ptr, map_size):
  105. VirtualFree_safe(ptr, 0, MEM_RELEASE)