tor  0.4.2.1-alpha-dev
map_anon.c
Go to the documentation of this file.
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 
11 #include "orconfig.h"
12 #include "lib/malloc/map_anon.h"
13 #include "lib/malloc/malloc.h"
14 #include "lib/err/torerr.h"
15 
16 #ifdef HAVE_SYS_MMAN_H
17 #include <sys/mman.h>
18 #endif
19 #ifdef HAVE_SYS_TYPES_H
20 #include <sys/types.h>
21 #endif
22 #ifdef HAVE_MACH_VM_INHERIT_H
23 #include <mach/vm_inherit.h>
24 #endif
25 
26 #ifdef _WIN32
27 #include <windows.h>
28 #endif
29 
30 #include <string.h>
31 #include <errno.h>
32 
38 #if SIZEOF_SIZE_T > 4
39 #define HIGH_SIZE_T_BYTES(sz) ((sz) >> 32)
40 #else
41 #define HIGH_SIZE_T_BYTES(sz) (0)
42 #endif
43 
44 /* Here we define a MINHERIT macro that is minherit() or madvise(), depending
45  * on what we actually want.
46  *
47  * If there's a flag that sets pages to zero after fork, we define FLAG_ZERO
48  * to be that flag. If there's a flag unmaps pages after fork, we define
49  * FLAG_NOINHERIT to be that flag.
50  */
51 #if defined(HAVE_MINHERIT)
52 #define MINHERIT minherit
53 
54 #ifdef INHERIT_ZERO
55 #define FLAG_ZERO INHERIT_ZERO
56 #elif defined(MAP_INHERIT_ZERO)
57 #define FLAG_ZERO MAP_INHERIT_ZERO
58 #endif
59 #ifdef INHERIT_NONE
60 #define FLAG_NOINHERIT INHERIT_NONE
61 #elif defined(VM_INHERIT_NONE)
62 #define FLAG_NOINHERIT VM_INHERIT_NONE
63 #elif defined(MAP_INHERIT_NONE)
64 #define FLAG_NOINHERIT MAP_INHERIT_NONE
65 #endif /* defined(INHERIT_NONE) || ... */
66 
67 #elif defined(HAVE_MADVISE)
68 
69 #define MINHERIT madvise
70 
71 #ifdef MADV_WIPEONFORK
72 #define FLAG_ZERO MADV_WIPEONFORK
73 #endif
74 #ifdef MADV_DONTFORK
75 #define FLAG_NOINHERIT MADV_DONTFORK
76 #endif
77 
78 #endif /* defined(HAVE_MINHERIT) || ... */
79 
80 #if defined(HAVE_MINHERIT) && !defined(FLAG_ZERO) && !defined(FLAG_NOINHERIT)
81 #warn "minherit() is defined, but we couldn't find the right flag for it."
82 #warn "This is probably a bug in Tor's support for this platform."
83 #endif
84 
90 static int
91 lock_mem(void *mem, size_t sz)
92 {
93 #ifdef _WIN32
94  return VirtualLock(mem, sz) ? 0 : -1;
95 #elif defined(HAVE_MLOCK)
96  return mlock(mem, sz);
97 #else
98  (void) mem;
99  (void) sz;
100 
101  return 0;
102 #endif /* defined(_WIN32) || ... */
103 }
104 
110 static int
111 nodump_mem(void *mem, size_t sz)
112 {
113 #if defined(MADV_DONTDUMP)
114  int rv = madvise(mem, sz, MADV_DONTDUMP);
115  if (rv == 0) {
116  return 0;
117  } else if (errno == ENOSYS || errno == EINVAL) {
118  return 0; // syscall not supported, or flag not supported.
119  } else {
120  tor_log_err_sigsafe("Unexpected error from madvise: ",
121  strerror(errno),
122  NULL);
123  return -1;
124  }
125 #else /* !(defined(MADV_DONTDUMP)) */
126  (void) mem;
127  (void) sz;
128  return 0;
129 #endif /* defined(MADV_DONTDUMP) */
130 }
131 
142 static int
143 noinherit_mem(void *mem, size_t sz, inherit_res_t *inherit_result_out)
144 {
145 #ifdef FLAG_ZERO
146  int r = MINHERIT(mem, sz, FLAG_ZERO);
147  if (r == 0) {
148  *inherit_result_out = INHERIT_RES_ZERO;
149  return 0;
150  }
151 #endif /* defined(FLAG_ZERO) */
152 
153 #ifdef FLAG_NOINHERIT
154  int r2 = MINHERIT(mem, sz, FLAG_NOINHERIT);
155  if (r2 == 0) {
156  *inherit_result_out = INHERIT_RES_DROP;
157  return 0;
158  }
159 #endif /* defined(FLAG_NOINHERIT) */
160 
161 #if defined(FLAG_ZERO) || defined(FLAG_NOINHERIT)
162  /* At least one operation was tried, and neither succeeded. */
163 
164  if (errno == ENOSYS || errno == EINVAL) {
165  /* Syscall not supported, or flag not supported. */
166  return 0;
167  } else {
168  tor_log_err_sigsafe("Unexpected error from minherit: ",
169  strerror(errno),
170  NULL);
171  return -1;
172  }
173 #else /* !(defined(FLAG_ZERO) || defined(FLAG_NOINHERIT)) */
174  (void)inherit_result_out;
175  (void)mem;
176  (void)sz;
177  return 0;
178 #endif /* defined(FLAG_ZERO) || defined(FLAG_NOINHERIT) */
179 }
180 
202 void *
203 tor_mmap_anonymous(size_t sz, unsigned flags,
204  inherit_res_t *inherit_result_out)
205 {
206  void *ptr;
207  inherit_res_t itmp=0;
208  if (inherit_result_out == NULL) {
209  inherit_result_out = &itmp;
210  }
211  *inherit_result_out = INHERIT_RES_KEEP;
212 
213 #if defined(_WIN32)
214  HANDLE mapping = CreateFileMapping(INVALID_HANDLE_VALUE,
215  NULL, /*attributes*/
216  PAGE_READWRITE,
217  HIGH_SIZE_T_BYTES(sz),
218  sz & 0xffffffff,
219  NULL /* name */);
220  raw_assert(mapping != NULL);
221  ptr = MapViewOfFile(mapping, FILE_MAP_WRITE,
222  0, 0, /* Offset */
223  0 /* Extend to end of mapping */);
224  raw_assert(ptr);
225  CloseHandle(mapping); /* mapped view holds a reference */
226 #elif defined(HAVE_SYS_MMAN_H)
227  ptr = mmap(NULL, sz,
228  PROT_READ|PROT_WRITE,
229  MAP_ANON|MAP_PRIVATE,
230  -1, 0);
231  raw_assert(ptr != MAP_FAILED);
232  raw_assert(ptr != NULL);
233 #else
234  ptr = tor_malloc_zero(sz);
235 #endif /* defined(_WIN32) || ... */
236 
237  if (flags & ANONMAP_PRIVATE) {
238  int lock_result = lock_mem(ptr, sz);
239  raw_assert(lock_result == 0);
240  int nodump_result = nodump_mem(ptr, sz);
241  raw_assert(nodump_result == 0);
242  }
243 
244  if (flags & ANONMAP_NOINHERIT) {
245  int noinherit_result = noinherit_mem(ptr, sz, inherit_result_out);
246  raw_assert(noinherit_result == 0);
247  }
248 
249  return ptr;
250 }
251 
256 void
257 tor_munmap_anonymous(void *mapping, size_t sz)
258 {
259  if (!mapping)
260  return;
261 
262 #if defined(_WIN32)
263  (void)sz;
264  UnmapViewOfFile(mapping);
265 #elif defined(HAVE_SYS_MMAN_H)
266  munmap(mapping, sz);
267 #else
268  (void)sz;
269  tor_free(mapping);
270 #endif /* defined(_WIN32) || ... */
271 }
static int lock_mem(void *mem, size_t sz)
Definition: map_anon.c:91
Headers for map_anon.c.
void tor_log_err_sigsafe(const char *m,...)
Definition: torerr.c:70
void tor_munmap_anonymous(void *mapping, size_t sz)
Definition: map_anon.c:257
#define tor_free(p)
Definition: malloc.h:52
Headers for util_malloc.c.
#define ANONMAP_NOINHERIT
Definition: map_anon.h:32
#define ANONMAP_PRIVATE
Definition: map_anon.h:23
inherit_res_t
Definition: map_anon.h:34
void * tor_mmap_anonymous(size_t sz, unsigned flags, inherit_res_t *inherit_result_out)
Definition: map_anon.c:203
static int nodump_mem(void *mem, size_t sz)
Definition: map_anon.c:111
#define HIGH_SIZE_T_BYTES(sz)
Definition: map_anon.c:41
Headers for torerr.c.
static int noinherit_mem(void *mem, size_t sz, inherit_res_t *inherit_result_out)
Definition: map_anon.c:143