1 /* 2 * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "e_os.h" 11 #include "internal/cryptlib.h" 12 #include "crypto/cryptlib.h" 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <limits.h> 16 #include <openssl/crypto.h> 17 #ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE 18 # include <execinfo.h> 19 #endif 20 21 /* 22 * the following pointers may be changed as long as 'allow_customize' is set 23 */ 24 static int allow_customize = 1; 25 26 static void *(*malloc_impl)(size_t, const char *, int) 27 = CRYPTO_malloc; 28 static void *(*realloc_impl)(void *, size_t, const char *, int) 29 = CRYPTO_realloc; 30 static void (*free_impl)(void *, const char *, int) 31 = CRYPTO_free; 32 33 #ifndef OPENSSL_NO_CRYPTO_MDEBUG 34 # include "internal/tsan_assist.h" 35 36 static TSAN_QUALIFIER int malloc_count; 37 static TSAN_QUALIFIER int realloc_count; 38 static TSAN_QUALIFIER int free_count; 39 40 # define INCREMENT(x) tsan_counter(&(x)) 41 42 static char *md_failstring; 43 static long md_count; 44 static int md_fail_percent = 0; 45 static int md_tracefd = -1; 46 static int call_malloc_debug = 1; 47 48 static void parseit(void); 49 static int shouldfail(void); 50 51 # define FAILTEST() if (shouldfail()) return NULL 52 53 #else 54 static int call_malloc_debug = 0; 55 56 # define INCREMENT(x) /* empty */ 57 # define FAILTEST() /* empty */ 58 #endif 59 60 int CRYPTO_set_mem_functions( 61 void *(*m)(size_t, const char *, int), 62 void *(*r)(void *, size_t, const char *, int), 63 void (*f)(void *, const char *, int)) 64 { 65 if (!allow_customize) 66 return 0; 67 if (m) 68 malloc_impl = m; 69 if (r) 70 realloc_impl = r; 71 if (f) 72 free_impl = f; 73 return 1; 74 } 75 76 int CRYPTO_set_mem_debug(int flag) 77 { 78 if (!allow_customize) 79 return 0; 80 call_malloc_debug = flag; 81 return 1; 82 } 83 84 void CRYPTO_get_mem_functions( 85 void *(**m)(size_t, const char *, int), 86 void *(**r)(void *, size_t, const char *, int), 87 void (**f)(void *, const char *, int)) 88 { 89 if (m != NULL) 90 *m = malloc_impl; 91 if (r != NULL) 92 *r = realloc_impl; 93 if (f != NULL) 94 *f = free_impl; 95 } 96 97 #ifndef OPENSSL_NO_CRYPTO_MDEBUG 98 void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount) 99 { 100 if (mcount != NULL) 101 *mcount = tsan_load(&malloc_count); 102 if (rcount != NULL) 103 *rcount = tsan_load(&realloc_count); 104 if (fcount != NULL) 105 *fcount = tsan_load(&free_count); 106 } 107 108 /* 109 * Parse a "malloc failure spec" string. This likes like a set of fields 110 * separated by semicolons. Each field has a count and an optional failure 111 * percentage. For example: 112 * 100@0;100@25;0@0 113 * or 100;100@25;0 114 * This means 100 mallocs succeed, then next 100 fail 25% of the time, and 115 * all remaining (count is zero) succeed. 116 */ 117 static void parseit(void) 118 { 119 char *semi = strchr(md_failstring, ';'); 120 char *atsign; 121 122 if (semi != NULL) 123 *semi++ = '\0'; 124 125 /* Get the count (atol will stop at the @ if there), and percentage */ 126 md_count = atol(md_failstring); 127 atsign = strchr(md_failstring, '@'); 128 md_fail_percent = atsign == NULL ? 0 : atoi(atsign + 1); 129 130 if (semi != NULL) 131 md_failstring = semi; 132 } 133 134 /* 135 * Windows doesn't have random(), but it has rand() 136 * Some rand() implementations aren't good, but we're not 137 * dealing with secure randomness here. 138 */ 139 # ifdef _WIN32 140 # define random() rand() 141 # endif 142 /* 143 * See if the current malloc should fail. 144 */ 145 static int shouldfail(void) 146 { 147 int roll = (int)(random() % 100); 148 int shoulditfail = roll < md_fail_percent; 149 # ifndef _WIN32 150 /* suppressed on Windows as POSIX-like file descriptors are non-inheritable */ 151 int len; 152 char buff[80]; 153 154 if (md_tracefd > 0) { 155 BIO_snprintf(buff, sizeof(buff), 156 "%c C%ld %%%d R%d\n", 157 shoulditfail ? '-' : '+', md_count, md_fail_percent, roll); 158 len = strlen(buff); 159 if (write(md_tracefd, buff, len) != len) 160 perror("shouldfail write failed"); 161 # ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE 162 if (shoulditfail) { 163 void *addrs[30]; 164 int num = backtrace(addrs, OSSL_NELEM(addrs)); 165 166 backtrace_symbols_fd(addrs, num, md_tracefd); 167 } 168 # endif 169 } 170 # endif 171 172 if (md_count) { 173 /* If we used up this one, go to the next. */ 174 if (--md_count == 0) 175 parseit(); 176 } 177 178 return shoulditfail; 179 } 180 181 void ossl_malloc_setup_failures(void) 182 { 183 const char *cp = getenv("OPENSSL_MALLOC_FAILURES"); 184 185 if (cp != NULL && (md_failstring = strdup(cp)) != NULL) 186 parseit(); 187 if ((cp = getenv("OPENSSL_MALLOC_FD")) != NULL) 188 md_tracefd = atoi(cp); 189 } 190 #endif 191 192 void *CRYPTO_malloc(size_t num, const char *file, int line) 193 { 194 void *ret = NULL; 195 196 INCREMENT(malloc_count); 197 if (malloc_impl != NULL && malloc_impl != CRYPTO_malloc) 198 return malloc_impl(num, file, line); 199 200 if (num == 0) 201 return NULL; 202 203 FAILTEST(); 204 if (allow_customize) { 205 /* 206 * Disallow customization after the first allocation. We only set this 207 * if necessary to avoid a store to the same cache line on every 208 * allocation. 209 */ 210 allow_customize = 0; 211 } 212 #ifndef OPENSSL_NO_CRYPTO_MDEBUG 213 if (call_malloc_debug) { 214 CRYPTO_mem_debug_malloc(NULL, num, 0, file, line); 215 ret = malloc(num); 216 CRYPTO_mem_debug_malloc(ret, num, 1, file, line); 217 } else { 218 ret = malloc(num); 219 } 220 #else 221 (void)(file); (void)(line); 222 ret = malloc(num); 223 #endif 224 225 return ret; 226 } 227 228 void *CRYPTO_zalloc(size_t num, const char *file, int line) 229 { 230 void *ret = CRYPTO_malloc(num, file, line); 231 232 FAILTEST(); 233 if (ret != NULL) 234 memset(ret, 0, num); 235 return ret; 236 } 237 238 void *CRYPTO_realloc(void *str, size_t num, const char *file, int line) 239 { 240 INCREMENT(realloc_count); 241 if (realloc_impl != NULL && realloc_impl != &CRYPTO_realloc) 242 return realloc_impl(str, num, file, line); 243 244 FAILTEST(); 245 if (str == NULL) 246 return CRYPTO_malloc(num, file, line); 247 248 if (num == 0) { 249 CRYPTO_free(str, file, line); 250 return NULL; 251 } 252 253 #ifndef OPENSSL_NO_CRYPTO_MDEBUG 254 if (call_malloc_debug) { 255 void *ret; 256 CRYPTO_mem_debug_realloc(str, NULL, num, 0, file, line); 257 ret = realloc(str, num); 258 CRYPTO_mem_debug_realloc(str, ret, num, 1, file, line); 259 return ret; 260 } 261 #else 262 (void)(file); (void)(line); 263 #endif 264 return realloc(str, num); 265 266 } 267 268 void *CRYPTO_clear_realloc(void *str, size_t old_len, size_t num, 269 const char *file, int line) 270 { 271 void *ret = NULL; 272 273 if (str == NULL) 274 return CRYPTO_malloc(num, file, line); 275 276 if (num == 0) { 277 CRYPTO_clear_free(str, old_len, file, line); 278 return NULL; 279 } 280 281 /* Can't shrink the buffer since memcpy below copies |old_len| bytes. */ 282 if (num < old_len) { 283 OPENSSL_cleanse((char*)str + num, old_len - num); 284 return str; 285 } 286 287 ret = CRYPTO_malloc(num, file, line); 288 if (ret != NULL) { 289 memcpy(ret, str, old_len); 290 CRYPTO_clear_free(str, old_len, file, line); 291 } 292 return ret; 293 } 294 295 void CRYPTO_free(void *str, const char *file, int line) 296 { 297 INCREMENT(free_count); 298 if (free_impl != NULL && free_impl != &CRYPTO_free) { 299 free_impl(str, file, line); 300 return; 301 } 302 303 #ifndef OPENSSL_NO_CRYPTO_MDEBUG 304 if (call_malloc_debug) { 305 CRYPTO_mem_debug_free(str, 0, file, line); 306 free(str); 307 CRYPTO_mem_debug_free(str, 1, file, line); 308 } else { 309 free(str); 310 } 311 #else 312 free(str); 313 #endif 314 } 315 316 void CRYPTO_clear_free(void *str, size_t num, const char *file, int line) 317 { 318 if (str == NULL) 319 return; 320 if (num) 321 OPENSSL_cleanse(str, num); 322 CRYPTO_free(str, file, line); 323 } 324