map_anon.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2019, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. /**
  6. * \file map_anon.c
  7. * \brief Manage anonymous mappings.
  8. **/
  9. #include "orconfig.h"
  10. #include "lib/malloc/map_anon.h"
  11. #include "lib/malloc/malloc.h"
  12. #include "lib/err/torerr.h"
  13. #ifdef HAVE_SYS_MMAN_H
  14. #include <sys/mman.h>
  15. #endif
  16. #ifdef HAVE_SYS_TYPES_H
  17. #include <sys/types.h>
  18. #endif
  19. #ifdef HAVE_MACH_VM_INHERIT_H
  20. #include <mach/vm_inherit.h>
  21. #endif
  22. #ifdef _WIN32
  23. #include <windows.h>
  24. #endif
  25. /**
  26. * Macro to get the high bytes of a size_t, if there are high bytes.
  27. * Windows needs this; other operating systems define a size_t that does
  28. * what it should.
  29. */
  30. #if SIZEOF_SIZE_T > 4
  31. #define HIGH_SIZE_T_BYTES(sz) ((sz) >> 32)
  32. #else
  33. #define HIGH_SIZE_T_BYTES(sz) (0)
  34. #endif
  35. /* Here we define a MINHERIT macro that is minherit() or madvise(), depending
  36. * on what we actually want.
  37. *
  38. * If there's a flag that sets pages to zero after fork, we define FLAG_ZERO
  39. * to be that flag. If there's a flag unmaps pages after fork, we define
  40. * FLAG_NOINHERIT to be that flag.
  41. */
  42. #if defined(HAVE_MINHERIT)
  43. #define MINHERIT minherit
  44. #ifdef INHERIT_ZERO
  45. #define FLAG_ZERO INHERIT_ZERO
  46. #endif
  47. #ifdef INHERIT_NONE
  48. #define FLAG_NOINHERIT INHERIT_NONE
  49. #elif defined(VM_INHERIT_NONE)
  50. #define FLAG_NOINHERIT VM_INHERIT_NONE
  51. #endif
  52. #elif defined(HAVE_MADVISE)
  53. #define MINHERIT madvise
  54. #ifdef MADV_WIPEONFORK
  55. #define FLAG_ZERO MADV_WIPEONFORK
  56. #endif
  57. #ifdef MADV_DONTFORK
  58. #define FLAG_NOINHERIT MADV_DONTFORK
  59. #endif
  60. #endif
  61. /**
  62. * Helper: try to prevent the <b>sz</b> bytes at <b>mem</b> from being swapped
  63. * to disk. Return 0 on success or if the facility is not available on this
  64. * OS; return -1 on failure.
  65. */
  66. static int
  67. lock_mem(void *mem, size_t sz)
  68. {
  69. #ifdef _WIN32
  70. return VirtualLock(mem, sz) ? 0 : -1;
  71. #elif defined(HAVE_MLOCK)
  72. return mlock(mem, sz);
  73. #else
  74. (void) mem;
  75. (void) sz;
  76. return 0;
  77. #endif
  78. }
  79. /**
  80. * Helper: try to prevent the <b>sz</b> bytes at <b>mem</b> from appearing in
  81. * a core dump. Return 0 on success or if the facility is not available on
  82. * this OS; return -1 on failure.
  83. */
  84. static int
  85. nodump_mem(void *mem, size_t sz)
  86. {
  87. #if defined(MADV_DONTDUMP)
  88. return madvise(mem, sz, MADV_DONTDUMP);
  89. #else
  90. (void) mem;
  91. (void) sz;
  92. return 0;
  93. #endif
  94. }
  95. /**
  96. * Helper: try to prevent the <b>sz</b> bytes at <b>mem</b> from being
  97. * accessible in child processes -- ideally by having them set to 0 after a
  98. * fork, and if that doesn't work, by having them unmapped after a fork.
  99. * Return 0 on success or if the facility is not available on this OS; return
  100. * -1 on failure.
  101. *
  102. * If we successfully make the memory uninheritable, adjust the value of
  103. * *<b>inherit_result_out</b>.
  104. */
  105. static int
  106. noinherit_mem(void *mem, size_t sz, unsigned *inherit_result_out)
  107. {
  108. #ifdef FLAG_ZERO
  109. int r = MINHERIT(mem, sz, FLAG_ZERO);
  110. if (r == 0) {
  111. *inherit_result_out = INHERIT_ZERO;
  112. return 0;
  113. }
  114. #endif
  115. #ifdef FLAG_NOINHERIT
  116. int r2 = MINHERIT(mem, sz, FLAG_NOINHERIT);
  117. if (r2 == 0) {
  118. *inherit_result_out = INHERIT_DROP;
  119. }
  120. return r2;
  121. #else
  122. (void)inherit_result_out;
  123. (void)mem;
  124. (void)sz;
  125. return 0;
  126. #endif
  127. }
  128. /**
  129. * Return a new anonymous memory mapping that holds <b>sz</b> bytes.
  130. *
  131. * Memory mappings are unlike the results from malloc() in that they are
  132. * handled separately by the operating system, and as such can have different
  133. * kernel-level flags set on them.
  134. *
  135. * The "flags" argument may be zero or more of ANONMAP_PRIVATE and
  136. * ANONMAP_NOINHERIT.
  137. *
  138. * Memory returned from this function must be released with
  139. * tor_munmap_anonymous().
  140. *
  141. * If <b>inherit_result_out</b> is non-NULL, set it to one of INHERIT_KEEP,
  142. * INHERIT_DROP, and INHERIT_ZERO, depending on the properties of the returned
  143. * memory.
  144. *
  145. * [Note: OS people use the word "anonymous" here to mean that the memory
  146. * isn't associated with any file. This has *nothing* to do with the kind of
  147. * anonymity that Tor is trying to provide.]
  148. */
  149. void *
  150. tor_mmap_anonymous(size_t sz, unsigned flags, unsigned *inherit_result_out)
  151. {
  152. void *ptr;
  153. unsigned itmp=0;
  154. if (inherit_result_out == NULL) {
  155. inherit_result_out = &itmp;
  156. }
  157. *inherit_result_out = INHERIT_KEEP;
  158. #if defined(_WIN32)
  159. HANDLE mapping = CreateFileMapping(INVALID_HANDLE_VALUE,
  160. NULL, /*attributes*/
  161. PAGE_READWRITE,
  162. HIGH_SIZE_T_BYTES(sz),
  163. sz & 0xffffffff,
  164. NULL /* name */);
  165. raw_assert(mapping != NULL);
  166. ptr = MapViewOfFile(mapping, FILE_MAP_WRITE,
  167. 0, 0, /* Offset */
  168. 0 /* Extend to end of mapping */);
  169. raw_assert(ptr);
  170. CloseHandle(mapping); /* mapped view holds a reference */
  171. #elif defined(HAVE_SYS_MMAN_H)
  172. ptr = mmap(NULL, sz,
  173. PROT_READ|PROT_WRITE,
  174. MAP_ANON|MAP_PRIVATE,
  175. -1, 0);
  176. raw_assert(ptr != MAP_FAILED);
  177. raw_assert(ptr != NULL);
  178. #else
  179. ptr = tor_malloc_zero(sz);
  180. #endif
  181. if (flags & ANONMAP_PRIVATE) {
  182. int lock_result = lock_mem(ptr, sz);
  183. raw_assert(lock_result == 0);
  184. int nodump_result = nodump_mem(ptr, sz);
  185. raw_assert(nodump_result == 0);
  186. }
  187. if (flags & ANONMAP_NOINHERIT) {
  188. int noinherit_result = noinherit_mem(ptr, sz, inherit_result_out);
  189. raw_assert(noinherit_result == 0);
  190. }
  191. return ptr;
  192. }
  193. /**
  194. * Release <b>sz</b> bytes of memory that were previously mapped at
  195. * <b>mapping</b> by tor_mmap_anonymous().
  196. **/
  197. void
  198. tor_munmap_anonymous(void *mapping, size_t sz)
  199. {
  200. if (!mapping)
  201. return;
  202. #if defined(_WIN32)
  203. (void)sz;
  204. UnmapViewOfFile(mapping);
  205. #elif defined(HAVE_SYS_MMAN_H)
  206. munmap(mapping, sz);
  207. #else
  208. (void)sz;
  209. tor_free(mapping);
  210. #endif
  211. }