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