map_anon.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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. #elif defined(MAP_INHERIT_ZERO)
  47. #define FLAG_ZERO MAP_INHERIT_ZERO
  48. #endif
  49. #ifdef INHERIT_NONE
  50. #define FLAG_NOINHERIT INHERIT_NONE
  51. #elif defined(VM_INHERIT_NONE)
  52. #define FLAG_NOINHERIT VM_INHERIT_NONE
  53. #elif defined(MAP_INHERIT_NONE)
  54. #define FLAG_NOINHERIT MAP_INHERIT_NONE
  55. #endif /* defined(INHERIT_NONE) || ... */
  56. #elif defined(HAVE_MADVISE)
  57. #define MINHERIT madvise
  58. #ifdef MADV_WIPEONFORK
  59. #define FLAG_ZERO MADV_WIPEONFORK
  60. #endif
  61. #ifdef MADV_DONTFORK
  62. #define FLAG_NOINHERIT MADV_DONTFORK
  63. #endif
  64. #endif /* defined(HAVE_MINHERIT) || ... */
  65. #if defined(HAVE_MINHERIT) && !defined(FLAG_ZERO) && !defined(FLAG_NOINHERIT)
  66. #warn "minherit() is defined, but we couldn't find the right flag for it."
  67. #warn "This is probably a bug in Tor's support for this platform."
  68. #endif
  69. /**
  70. * Helper: try to prevent the <b>sz</b> bytes at <b>mem</b> from being swapped
  71. * to disk. Return 0 on success or if the facility is not available on this
  72. * OS; return -1 on failure.
  73. */
  74. static int
  75. lock_mem(void *mem, size_t sz)
  76. {
  77. #ifdef _WIN32
  78. return VirtualLock(mem, sz) ? 0 : -1;
  79. #elif defined(HAVE_MLOCK)
  80. return mlock(mem, sz);
  81. #else
  82. (void) mem;
  83. (void) sz;
  84. return 0;
  85. #endif /* defined(_WIN32) || ... */
  86. }
  87. /**
  88. * Helper: try to prevent the <b>sz</b> bytes at <b>mem</b> from appearing in
  89. * a core dump. Return 0 on success or if the facility is not available on
  90. * this OS; return -1 on failure.
  91. */
  92. static int
  93. nodump_mem(void *mem, size_t sz)
  94. {
  95. #if defined(MADV_DONTDUMP)
  96. return madvise(mem, sz, MADV_DONTDUMP);
  97. #else
  98. (void) mem;
  99. (void) sz;
  100. return 0;
  101. #endif /* defined(MADV_DONTDUMP) */
  102. }
  103. /**
  104. * Helper: try to prevent the <b>sz</b> bytes at <b>mem</b> from being
  105. * accessible in child processes -- ideally by having them set to 0 after a
  106. * fork, and if that doesn't work, by having them unmapped after a fork.
  107. * Return 0 on success or if the facility is not available on this OS; return
  108. * -1 on failure.
  109. *
  110. * If we successfully make the memory uninheritable, adjust the value of
  111. * *<b>inherit_result_out</b>.
  112. */
  113. static int
  114. noinherit_mem(void *mem, size_t sz, inherit_res_t *inherit_result_out)
  115. {
  116. #ifdef FLAG_ZERO
  117. int r = MINHERIT(mem, sz, FLAG_ZERO);
  118. if (r == 0) {
  119. *inherit_result_out = INHERIT_RES_ZERO;
  120. return 0;
  121. }
  122. #endif /* defined(FLAG_ZERO) */
  123. #ifdef FLAG_NOINHERIT
  124. int r2 = MINHERIT(mem, sz, FLAG_NOINHERIT);
  125. if (r2 == 0) {
  126. *inherit_result_out = INHERIT_RES_DROP;
  127. }
  128. return r2;
  129. #else /* !(defined(FLAG_NOINHERIT)) */
  130. (void)inherit_result_out;
  131. (void)mem;
  132. (void)sz;
  133. return 0;
  134. #endif /* defined(FLAG_NOINHERIT) */
  135. }
  136. /**
  137. * Return a new anonymous memory mapping that holds <b>sz</b> bytes.
  138. *
  139. * Memory mappings are unlike the results from malloc() in that they are
  140. * handled separately by the operating system, and as such can have different
  141. * kernel-level flags set on them.
  142. *
  143. * The "flags" argument may be zero or more of ANONMAP_PRIVATE and
  144. * ANONMAP_NOINHERIT.
  145. *
  146. * Memory returned from this function must be released with
  147. * tor_munmap_anonymous().
  148. *
  149. * If <b>inherit_result_out</b> is non-NULL, set it to one of
  150. * INHERIT_RES_KEEP, INHERIT_RES_DROP, or INHERIT_RES_ZERO, depending on the
  151. * properties of the returned memory.
  152. *
  153. * [Note: OS people use the word "anonymous" here to mean that the memory
  154. * isn't associated with any file. This has *nothing* to do with the kind of
  155. * anonymity that Tor is trying to provide.]
  156. */
  157. void *
  158. tor_mmap_anonymous(size_t sz, unsigned flags,
  159. inherit_res_t *inherit_result_out)
  160. {
  161. void *ptr;
  162. inherit_res_t itmp=0;
  163. if (inherit_result_out == NULL) {
  164. inherit_result_out = &itmp;
  165. }
  166. *inherit_result_out = INHERIT_RES_KEEP;
  167. #if defined(_WIN32)
  168. HANDLE mapping = CreateFileMapping(INVALID_HANDLE_VALUE,
  169. NULL, /*attributes*/
  170. PAGE_READWRITE,
  171. HIGH_SIZE_T_BYTES(sz),
  172. sz & 0xffffffff,
  173. NULL /* name */);
  174. raw_assert(mapping != NULL);
  175. ptr = MapViewOfFile(mapping, FILE_MAP_WRITE,
  176. 0, 0, /* Offset */
  177. 0 /* Extend to end of mapping */);
  178. raw_assert(ptr);
  179. CloseHandle(mapping); /* mapped view holds a reference */
  180. #elif defined(HAVE_SYS_MMAN_H)
  181. ptr = mmap(NULL, sz,
  182. PROT_READ|PROT_WRITE,
  183. MAP_ANON|MAP_PRIVATE,
  184. -1, 0);
  185. raw_assert(ptr != MAP_FAILED);
  186. raw_assert(ptr != NULL);
  187. #else
  188. ptr = tor_malloc_zero(sz);
  189. #endif /* defined(_WIN32) || ... */
  190. if (flags & ANONMAP_PRIVATE) {
  191. int lock_result = lock_mem(ptr, sz);
  192. raw_assert(lock_result == 0);
  193. int nodump_result = nodump_mem(ptr, sz);
  194. raw_assert(nodump_result == 0);
  195. }
  196. if (flags & ANONMAP_NOINHERIT) {
  197. int noinherit_result = noinherit_mem(ptr, sz, inherit_result_out);
  198. raw_assert(noinherit_result == 0);
  199. }
  200. return ptr;
  201. }
  202. /**
  203. * Release <b>sz</b> bytes of memory that were previously mapped at
  204. * <b>mapping</b> by tor_mmap_anonymous().
  205. **/
  206. void
  207. tor_munmap_anonymous(void *mapping, size_t sz)
  208. {
  209. if (!mapping)
  210. return;
  211. #if defined(_WIN32)
  212. (void)sz;
  213. UnmapViewOfFile(mapping);
  214. #elif defined(HAVE_SYS_MMAN_H)
  215. munmap(mapping, sz);
  216. #else
  217. (void)sz;
  218. tor_free(mapping);
  219. #endif /* defined(_WIN32) || ... */
  220. }