map_anon.c (7439B)
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 }