Tor  0.4.7.0-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-2021, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
6 /**
7  * \file map_anon.c
8  * \brief Manage anonymous mappings.
9  **/
10 
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 
33 /**
34  * Macro to get the high bytes of a size_t, if there are high bytes.
35  * Windows needs this; other operating systems define a size_t that does
36  * what it should.
37  */
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 #warning "minherit() is defined, but FLAG_ZERO/NOINHERIT are not."
82 #warning "This is probably a bug in Tor's support for this platform."
83 #endif
84 
85 /**
86  * Helper: try to prevent the <b>sz</b> bytes at <b>mem</b> from being swapped
87  * to disk. Return 0 on success or if the facility is not available on this
88  * OS; return -1 on failure.
89  */
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 
105 /**
106  * Helper: try to prevent the <b>sz</b> bytes at <b>mem</b> from appearing in
107  * a core dump. Return 0 on success or if the facility is not available on
108  * this OS; return -1 on failure.
109  */
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 
132 /**
133  * Helper: try to prevent the <b>sz</b> bytes at <b>mem</b> from being
134  * accessible in child processes -- ideally by having them set to 0 after a
135  * fork, and if that doesn't work, by having them unmapped after a fork.
136  * Return 0 on success or if the facility is not available on this OS; return
137  * -1 on failure.
138  *
139  * If we successfully make the memory uninheritable, adjust the value of
140  * *<b>inherit_result_out</b>.
141  */
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 
181 /**
182  * Return a new anonymous memory mapping that holds <b>sz</b> bytes.
183  *
184  * Memory mappings are unlike the results from malloc() in that they are
185  * handled separately by the operating system, and as such can have different
186  * kernel-level flags set on them.
187  *
188  * The "flags" argument may be zero or more of ANONMAP_PRIVATE and
189  * ANONMAP_NOINHERIT.
190  *
191  * Memory returned from this function must be released with
192  * tor_munmap_anonymous().
193  *
194  * If <b>inherit_result_out</b> is non-NULL, set it to one of
195  * INHERIT_RES_KEEP, INHERIT_RES_DROP, or INHERIT_RES_ZERO, depending on the
196  * properties of the returned memory.
197  *
198  * [Note: OS people use the word "anonymous" here to mean that the memory
199  * isn't associated with any file. This has *nothing* to do with the kind of
200  * anonymity that Tor is trying to provide.]
201  */
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 
252 /**
253  * Release <b>sz</b> bytes of memory that were previously mapped at
254  * <b>mapping</b> by tor_mmap_anonymous().
255  **/
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 }
Headers for util_malloc.c.
#define tor_free(p)
Definition: malloc.h:52
static int noinherit_mem(void *mem, size_t sz, inherit_res_t *inherit_result_out)
Definition: map_anon.c:143
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
void tor_munmap_anonymous(void *mapping, size_t sz)
Definition: map_anon.c:257
static int lock_mem(void *mem, size_t sz)
Definition: map_anon.c:91
void * tor_mmap_anonymous(size_t sz, unsigned flags, inherit_res_t *inherit_result_out)
Definition: map_anon.c:203
Headers for map_anon.c.
inherit_res_t
Definition: map_anon.h:34
@ INHERIT_RES_DROP
Definition: map_anon.h:40
@ INHERIT_RES_KEEP
Definition: map_anon.h:37
@ INHERIT_RES_ZERO
Definition: map_anon.h:43
#define ANONMAP_PRIVATE
Definition: map_anon.h:23
#define ANONMAP_NOINHERIT
Definition: map_anon.h:32
void tor_log_err_sigsafe(const char *m,...)
Definition: torerr.c:70
Headers for torerr.c.