map_anon.c 7.3 KB

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