Tor 0.4.9.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 */
90static int
91lock_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 */
110static int
111nodump_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 */
142static int
143noinherit_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 */
202void *
203tor_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,
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 **/
256void
257tor_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:56
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.