1 /* Copyright (c) 2003-2004, Roger Dingledine
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2020, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
8 * \brief Manage anonymous mappings.
12 #include "lib/malloc/map_anon.h"
13 #include "lib/malloc/malloc.h"
14 #include "lib/err/torerr.h"
16 #ifdef HAVE_SYS_MMAN_H
19 #ifdef HAVE_SYS_TYPES_H
20 #include <sys/types.h>
22 #ifdef HAVE_MACH_VM_INHERIT_H
23 #include <mach/vm_inherit.h>
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
39 #define HIGH_SIZE_T_BYTES(sz) ((sz) >> 32)
41 #define HIGH_SIZE_T_BYTES(sz) (0)
44 /* Here we define a MINHERIT macro that is minherit() or madvise(), depending
45 * on what we actually want.
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.
51 #if defined(HAVE_MINHERIT)
52 #define MINHERIT minherit
55 #define FLAG_ZERO INHERIT_ZERO
56 #elif defined(MAP_INHERIT_ZERO)
57 #define FLAG_ZERO MAP_INHERIT_ZERO
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) || ... */
67 #elif defined(HAVE_MADVISE)
69 #define MINHERIT madvise
71 #ifdef MADV_WIPEONFORK
72 #define FLAG_ZERO MADV_WIPEONFORK
75 #define FLAG_NOINHERIT MADV_DONTFORK
78 #endif /* defined(HAVE_MINHERIT) || ... */
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."
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.
91 lock_mem(void *mem
, size_t sz
)
94 return VirtualLock(mem
, sz
) ? 0 : -1;
95 #elif defined(HAVE_MLOCK)
96 return mlock(mem
, sz
);
102 #endif /* defined(_WIN32) || ... */
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.
111 nodump_mem(void *mem
, size_t sz
)
113 #if defined(MADV_DONTDUMP)
114 int rv
= madvise(mem
, sz
, MADV_DONTDUMP
);
117 } else if (errno
== ENOSYS
|| errno
== EINVAL
) {
118 return 0; // syscall not supported, or flag not supported.
120 tor_log_err_sigsafe("Unexpected error from madvise: ",
125 #else /* !defined(MADV_DONTDUMP) */
129 #endif /* defined(MADV_DONTDUMP) */
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
139 * If we successfully make the memory uninheritable, adjust the value of
140 * *<b>inherit_result_out</b>.
143 noinherit_mem(void *mem
, size_t sz
, inherit_res_t
*inherit_result_out
)
146 int r
= MINHERIT(mem
, sz
, FLAG_ZERO
);
148 *inherit_result_out
= INHERIT_RES_ZERO
;
151 #endif /* defined(FLAG_ZERO) */
153 #ifdef FLAG_NOINHERIT
154 int r2
= MINHERIT(mem
, sz
, FLAG_NOINHERIT
);
156 *inherit_result_out
= INHERIT_RES_DROP
;
159 #endif /* defined(FLAG_NOINHERIT) */
161 #if defined(FLAG_ZERO) || defined(FLAG_NOINHERIT)
162 /* At least one operation was tried, and neither succeeded. */
164 if (errno
== ENOSYS
|| errno
== EINVAL
) {
165 /* Syscall not supported, or flag not supported. */
168 tor_log_err_sigsafe("Unexpected error from minherit: ",
173 #else /* !(defined(FLAG_ZERO) || defined(FLAG_NOINHERIT)) */
174 (void)inherit_result_out
;
178 #endif /* defined(FLAG_ZERO) || defined(FLAG_NOINHERIT) */
182 * Return a new anonymous memory mapping that holds <b>sz</b> bytes.
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.
188 * The "flags" argument may be zero or more of ANONMAP_PRIVATE and
191 * Memory returned from this function must be released with
192 * tor_munmap_anonymous().
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.
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.]
203 tor_mmap_anonymous(size_t sz
, unsigned flags
,
204 inherit_res_t
*inherit_result_out
)
207 inherit_res_t itmp
=0;
208 if (inherit_result_out
== NULL
) {
209 inherit_result_out
= &itmp
;
211 *inherit_result_out
= INHERIT_RES_KEEP
;
214 HANDLE mapping
= CreateFileMapping(INVALID_HANDLE_VALUE
,
217 HIGH_SIZE_T_BYTES(sz
),
220 raw_assert(mapping
!= NULL
);
221 ptr
= MapViewOfFile(mapping
, FILE_MAP_WRITE
,
223 0 /* Extend to end of mapping */);
225 CloseHandle(mapping
); /* mapped view holds a reference */
226 #elif defined(HAVE_SYS_MMAN_H)
228 PROT_READ
|PROT_WRITE
,
229 MAP_ANON
|MAP_PRIVATE
,
231 raw_assert(ptr
!= MAP_FAILED
);
232 raw_assert(ptr
!= NULL
);
234 ptr
= tor_malloc_zero(sz
);
235 #endif /* defined(_WIN32) || ... */
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);
244 if (flags
& ANONMAP_NOINHERIT
) {
245 int noinherit_result
= noinherit_mem(ptr
, sz
, inherit_result_out
);
246 raw_assert(noinherit_result
== 0);
253 * Release <b>sz</b> bytes of memory that were previously mapped at
254 * <b>mapping</b> by tor_mmap_anonymous().
257 tor_munmap_anonymous(void *mapping
, size_t sz
)
264 UnmapViewOfFile(mapping
);
265 #elif defined(HAVE_SYS_MMAN_H)
270 #endif /* defined(_WIN32) || ... */