14ec2eca9Schristos /*
2*5b10f583Schristos  * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
3a89c9211Schristos  *
4*5b10f583Schristos  * Licensed under the Apache License 2.0 (the "License").  You may not use
54ec2eca9Schristos  * this file except in compliance with the License.  You can obtain a copy
64ec2eca9Schristos  * in the file LICENSE in the source distribution or at
74ec2eca9Schristos  * https://www.openssl.org/source/license.html
8a89c9211Schristos  */
9a89c9211Schristos 
10e7ccb6d1Schristos #include "e_os.h"
11e7ccb6d1Schristos #include "internal/cryptlib.h"
12cb006352Schristos #include "crypto/cryptlib.h"
13a89c9211Schristos #include <stdio.h>
14a89c9211Schristos #include <stdlib.h>
154ec2eca9Schristos #include <limits.h>
16a89c9211Schristos #include <openssl/crypto.h>
17a89c9211Schristos 
18d572d25fSspz /*
19d572d25fSspz  * the following pointers may be changed as long as 'allow_customize' is set
20d572d25fSspz  */
214ec2eca9Schristos static int allow_customize = 1;
22*5b10f583Schristos static CRYPTO_malloc_fn malloc_impl = CRYPTO_malloc;
23*5b10f583Schristos static CRYPTO_realloc_fn realloc_impl = CRYPTO_realloc;
24*5b10f583Schristos static CRYPTO_free_fn free_impl = CRYPTO_free;
25a89c9211Schristos 
26*5b10f583Schristos #if !defined(OPENSSL_NO_CRYPTO_MDEBUG) && !defined(FIPS_MODULE)
27e7ccb6d1Schristos # include "internal/tsan_assist.h"
28e7ccb6d1Schristos 
29*5b10f583Schristos # ifdef TSAN_REQUIRES_LOCKING
30*5b10f583Schristos #  define INCREMENT(x) /* empty */
31*5b10f583Schristos #  define LOAD(x) 0
32*5b10f583Schristos # else  /* TSAN_REQUIRES_LOCKING */
33e7ccb6d1Schristos static TSAN_QUALIFIER int malloc_count;
34e7ccb6d1Schristos static TSAN_QUALIFIER int realloc_count;
35e7ccb6d1Schristos static TSAN_QUALIFIER int free_count;
36e7ccb6d1Schristos 
37e7ccb6d1Schristos #  define INCREMENT(x) tsan_counter(&(x))
38*5b10f583Schristos #  define LOAD(x)      tsan_load(&x)
39*5b10f583Schristos # endif /* TSAN_REQUIRES_LOCKING */
40e7ccb6d1Schristos 
41e7ccb6d1Schristos static char *md_failstring;
42e7ccb6d1Schristos static long md_count;
43e7ccb6d1Schristos static int md_fail_percent = 0;
44e7ccb6d1Schristos static int md_tracefd = -1;
45e7ccb6d1Schristos 
46e7ccb6d1Schristos static void parseit(void);
47e7ccb6d1Schristos static int shouldfail(void);
48e7ccb6d1Schristos 
49e7ccb6d1Schristos # define FAILTEST() if (shouldfail()) return NULL
50e7ccb6d1Schristos 
514ec2eca9Schristos #else
52e7ccb6d1Schristos 
53e7ccb6d1Schristos # define INCREMENT(x) /* empty */
54e7ccb6d1Schristos # define FAILTEST() /* empty */
554ec2eca9Schristos #endif
564ec2eca9Schristos 
CRYPTO_set_mem_functions(CRYPTO_malloc_fn malloc_fn,CRYPTO_realloc_fn realloc_fn,CRYPTO_free_fn free_fn)57*5b10f583Schristos int CRYPTO_set_mem_functions(CRYPTO_malloc_fn malloc_fn,
58*5b10f583Schristos                              CRYPTO_realloc_fn realloc_fn,
59*5b10f583Schristos                              CRYPTO_free_fn free_fn)
60d572d25fSspz {
614ec2eca9Schristos     if (!allow_customize)
624ec2eca9Schristos         return 0;
63*5b10f583Schristos     if (malloc_fn != NULL)
64*5b10f583Schristos         malloc_impl = malloc_fn;
65*5b10f583Schristos     if (realloc_fn != NULL)
66*5b10f583Schristos         realloc_impl = realloc_fn;
67*5b10f583Schristos     if (free_fn != NULL)
68*5b10f583Schristos         free_impl = free_fn;
694ec2eca9Schristos     return 1;
70d572d25fSspz }
71d572d25fSspz 
CRYPTO_get_mem_functions(CRYPTO_malloc_fn * malloc_fn,CRYPTO_realloc_fn * realloc_fn,CRYPTO_free_fn * free_fn)72*5b10f583Schristos void CRYPTO_get_mem_functions(CRYPTO_malloc_fn *malloc_fn,
73*5b10f583Schristos                               CRYPTO_realloc_fn *realloc_fn,
74*5b10f583Schristos                               CRYPTO_free_fn *free_fn)
754ec2eca9Schristos {
76*5b10f583Schristos     if (malloc_fn != NULL)
77*5b10f583Schristos         *malloc_fn = malloc_impl;
78*5b10f583Schristos     if (realloc_fn != NULL)
79*5b10f583Schristos         *realloc_fn = realloc_impl;
80*5b10f583Schristos     if (free_fn != NULL)
81*5b10f583Schristos         *free_fn = free_impl;
824ec2eca9Schristos }
83a89c9211Schristos 
84*5b10f583Schristos #if !defined(OPENSSL_NO_CRYPTO_MDEBUG) && !defined(FIPS_MODULE)
CRYPTO_get_alloc_counts(int * mcount,int * rcount,int * fcount)85e7ccb6d1Schristos void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount)
86e7ccb6d1Schristos {
87e7ccb6d1Schristos     if (mcount != NULL)
88*5b10f583Schristos         *mcount = LOAD(malloc_count);
89e7ccb6d1Schristos     if (rcount != NULL)
90*5b10f583Schristos         *rcount = LOAD(realloc_count);
91e7ccb6d1Schristos     if (fcount != NULL)
92*5b10f583Schristos         *fcount = LOAD(free_count);
93e7ccb6d1Schristos }
94e7ccb6d1Schristos 
95e7ccb6d1Schristos /*
96e7ccb6d1Schristos  * Parse a "malloc failure spec" string.  This likes like a set of fields
97e7ccb6d1Schristos  * separated by semicolons.  Each field has a count and an optional failure
98e7ccb6d1Schristos  * percentage.  For example:
99e7ccb6d1Schristos  *          100@0;100@25;0@0
100e7ccb6d1Schristos  *    or    100;100@25;0
101e7ccb6d1Schristos  * This means 100 mallocs succeed, then next 100 fail 25% of the time, and
102e7ccb6d1Schristos  * all remaining (count is zero) succeed.
103e7ccb6d1Schristos  */
parseit(void)104e7ccb6d1Schristos static void parseit(void)
105e7ccb6d1Schristos {
106e7ccb6d1Schristos     char *semi = strchr(md_failstring, ';');
107e7ccb6d1Schristos     char *atsign;
108e7ccb6d1Schristos 
109e7ccb6d1Schristos     if (semi != NULL)
110e7ccb6d1Schristos         *semi++ = '\0';
111e7ccb6d1Schristos 
112e7ccb6d1Schristos     /* Get the count (atol will stop at the @ if there), and percentage */
113e7ccb6d1Schristos     md_count = atol(md_failstring);
114e7ccb6d1Schristos     atsign = strchr(md_failstring, '@');
115e7ccb6d1Schristos     md_fail_percent = atsign == NULL ? 0 : atoi(atsign + 1);
116e7ccb6d1Schristos 
117e7ccb6d1Schristos     if (semi != NULL)
118e7ccb6d1Schristos         md_failstring = semi;
119e7ccb6d1Schristos }
120e7ccb6d1Schristos 
121e7ccb6d1Schristos /*
122e7ccb6d1Schristos  * Windows doesn't have random(), but it has rand()
123e7ccb6d1Schristos  * Some rand() implementations aren't good, but we're not
124e7ccb6d1Schristos  * dealing with secure randomness here.
125e7ccb6d1Schristos  */
126e7ccb6d1Schristos # ifdef _WIN32
127e7ccb6d1Schristos #  define random() rand()
128e7ccb6d1Schristos # endif
129e7ccb6d1Schristos /*
130e7ccb6d1Schristos  * See if the current malloc should fail.
131e7ccb6d1Schristos  */
shouldfail(void)132e7ccb6d1Schristos static int shouldfail(void)
133e7ccb6d1Schristos {
134e7ccb6d1Schristos     int roll = (int)(random() % 100);
135e7ccb6d1Schristos     int shoulditfail = roll < md_fail_percent;
136e7ccb6d1Schristos # ifndef _WIN32
137e7ccb6d1Schristos /* suppressed on Windows as POSIX-like file descriptors are non-inheritable */
138e7ccb6d1Schristos     int len;
139e7ccb6d1Schristos     char buff[80];
140e7ccb6d1Schristos 
141e7ccb6d1Schristos     if (md_tracefd > 0) {
142e7ccb6d1Schristos         BIO_snprintf(buff, sizeof(buff),
143e7ccb6d1Schristos                      "%c C%ld %%%d R%d\n",
144e7ccb6d1Schristos                      shoulditfail ? '-' : '+', md_count, md_fail_percent, roll);
145e7ccb6d1Schristos         len = strlen(buff);
146e7ccb6d1Schristos         if (write(md_tracefd, buff, len) != len)
147e7ccb6d1Schristos             perror("shouldfail write failed");
148e7ccb6d1Schristos     }
149e7ccb6d1Schristos # endif
150e7ccb6d1Schristos 
151e7ccb6d1Schristos     if (md_count) {
152e7ccb6d1Schristos         /* If we used up this one, go to the next. */
153e7ccb6d1Schristos         if (--md_count == 0)
154e7ccb6d1Schristos             parseit();
155e7ccb6d1Schristos     }
156e7ccb6d1Schristos 
157e7ccb6d1Schristos     return shoulditfail;
158e7ccb6d1Schristos }
159e7ccb6d1Schristos 
ossl_malloc_setup_failures(void)160e7ccb6d1Schristos void ossl_malloc_setup_failures(void)
161e7ccb6d1Schristos {
162e7ccb6d1Schristos     const char *cp = getenv("OPENSSL_MALLOC_FAILURES");
163e7ccb6d1Schristos 
164e7ccb6d1Schristos     if (cp != NULL && (md_failstring = strdup(cp)) != NULL)
165e7ccb6d1Schristos         parseit();
166e7ccb6d1Schristos     if ((cp = getenv("OPENSSL_MALLOC_FD")) != NULL)
167e7ccb6d1Schristos         md_tracefd = atoi(cp);
168e7ccb6d1Schristos }
169e7ccb6d1Schristos #endif
170e7ccb6d1Schristos 
CRYPTO_malloc(size_t num,const char * file,int line)1714ec2eca9Schristos void *CRYPTO_malloc(size_t num, const char *file, int line)
1724ec2eca9Schristos {
173e7ccb6d1Schristos     INCREMENT(malloc_count);
174*5b10f583Schristos     if (malloc_impl != CRYPTO_malloc)
1754ec2eca9Schristos         return malloc_impl(num, file, line);
1764ec2eca9Schristos 
1774ec2eca9Schristos     if (num == 0)
1784ec2eca9Schristos         return NULL;
1794ec2eca9Schristos 
180e7ccb6d1Schristos     FAILTEST();
1813afa6631Schristos     if (allow_customize) {
1823afa6631Schristos         /*
1833afa6631Schristos          * Disallow customization after the first allocation. We only set this
1843afa6631Schristos          * if necessary to avoid a store to the same cache line on every
1853afa6631Schristos          * allocation.
1863afa6631Schristos          */
1874ec2eca9Schristos         allow_customize = 0;
1883afa6631Schristos     }
1897fa80bafSspz 
190*5b10f583Schristos     return malloc(num);
1914ec2eca9Schristos }
1924ec2eca9Schristos 
CRYPTO_zalloc(size_t num,const char * file,int line)1934ec2eca9Schristos void *CRYPTO_zalloc(size_t num, const char *file, int line)
1944ec2eca9Schristos {
195*5b10f583Schristos     void *ret;
1964ec2eca9Schristos 
197*5b10f583Schristos     ret = CRYPTO_malloc(num, file, line);
198e7ccb6d1Schristos     FAILTEST();
1994ec2eca9Schristos     if (ret != NULL)
2004ec2eca9Schristos         memset(ret, 0, num);
201*5b10f583Schristos 
2024ec2eca9Schristos     return ret;
2034ec2eca9Schristos }
2044ec2eca9Schristos 
CRYPTO_realloc(void * str,size_t num,const char * file,int line)2054ec2eca9Schristos void *CRYPTO_realloc(void *str, size_t num, const char *file, int line)
2064ec2eca9Schristos {
207e7ccb6d1Schristos     INCREMENT(realloc_count);
208*5b10f583Schristos     if (realloc_impl != CRYPTO_realloc)
2094ec2eca9Schristos         return realloc_impl(str, num, file, line);
2104ec2eca9Schristos 
211e7ccb6d1Schristos     FAILTEST();
2124ec2eca9Schristos     if (str == NULL)
2134ec2eca9Schristos         return CRYPTO_malloc(num, file, line);
2144ec2eca9Schristos 
2154ec2eca9Schristos     if (num == 0) {
2164ec2eca9Schristos         CRYPTO_free(str, file, line);
2174ec2eca9Schristos         return NULL;
2184ec2eca9Schristos     }
2194ec2eca9Schristos 
2204ec2eca9Schristos     return realloc(str, num);
2214ec2eca9Schristos }
2224ec2eca9Schristos 
CRYPTO_clear_realloc(void * str,size_t old_len,size_t num,const char * file,int line)2234ec2eca9Schristos void *CRYPTO_clear_realloc(void *str, size_t old_len, size_t num,
224a89c9211Schristos                            const char *file, int line)
225d572d25fSspz {
226a89c9211Schristos     void *ret = NULL;
227a89c9211Schristos 
228a89c9211Schristos     if (str == NULL)
229a89c9211Schristos         return CRYPTO_malloc(num, file, line);
230a89c9211Schristos 
2314ec2eca9Schristos     if (num == 0) {
2324ec2eca9Schristos         CRYPTO_clear_free(str, old_len, file, line);
233d572d25fSspz         return NULL;
234a89c9211Schristos     }
235a89c9211Schristos 
2364ec2eca9Schristos     /* Can't shrink the buffer since memcpy below copies |old_len| bytes. */
2374ec2eca9Schristos     if (num < old_len) {
2384ec2eca9Schristos         OPENSSL_cleanse((char*)str + num, old_len - num);
2394ec2eca9Schristos         return str;
2404ec2eca9Schristos     }
241a89c9211Schristos 
2424ec2eca9Schristos     ret = CRYPTO_malloc(num, file, line);
2434ec2eca9Schristos     if (ret != NULL) {
244a89c9211Schristos         memcpy(ret, str, old_len);
2454ec2eca9Schristos         CRYPTO_clear_free(str, old_len, file, line);
246a89c9211Schristos     }
247a89c9211Schristos     return ret;
248a89c9211Schristos }
249a89c9211Schristos 
CRYPTO_free(void * str,const char * file,int line)2504ec2eca9Schristos void CRYPTO_free(void *str, const char *file, int line)
251a89c9211Schristos {
252e7ccb6d1Schristos     INCREMENT(free_count);
253*5b10f583Schristos     if (free_impl != CRYPTO_free) {
2544ec2eca9Schristos         free_impl(str, file, line);
2554ec2eca9Schristos         return;
2564ec2eca9Schristos     }
2574ec2eca9Schristos 
2584ec2eca9Schristos     free(str);
259a89c9211Schristos }
260a89c9211Schristos 
CRYPTO_clear_free(void * str,size_t num,const char * file,int line)2614ec2eca9Schristos void CRYPTO_clear_free(void *str, size_t num, const char *file, int line)
262a89c9211Schristos {
2634ec2eca9Schristos     if (str == NULL)
2644ec2eca9Schristos         return;
2654ec2eca9Schristos     if (num)
2664ec2eca9Schristos         OPENSSL_cleanse(str, num);
2674ec2eca9Schristos     CRYPTO_free(str, file, line);
268a89c9211Schristos }
269*5b10f583Schristos 
270*5b10f583Schristos #if !defined(OPENSSL_NO_CRYPTO_MDEBUG)
271*5b10f583Schristos 
272*5b10f583Schristos # ifndef OPENSSL_NO_DEPRECATED_3_0
CRYPTO_mem_ctrl(int mode)273*5b10f583Schristos int CRYPTO_mem_ctrl(int mode)
274*5b10f583Schristos {
275*5b10f583Schristos     (void)mode;
276*5b10f583Schristos     return -1;
277*5b10f583Schristos }
278*5b10f583Schristos 
CRYPTO_set_mem_debug(int flag)279*5b10f583Schristos int CRYPTO_set_mem_debug(int flag)
280*5b10f583Schristos {
281*5b10f583Schristos     (void)flag;
282*5b10f583Schristos     return -1;
283*5b10f583Schristos }
284*5b10f583Schristos 
CRYPTO_mem_debug_push(const char * info,const char * file,int line)285*5b10f583Schristos int CRYPTO_mem_debug_push(const char *info, const char *file, int line)
286*5b10f583Schristos {
287*5b10f583Schristos     (void)info; (void)file; (void)line;
288*5b10f583Schristos     return 0;
289*5b10f583Schristos }
290*5b10f583Schristos 
CRYPTO_mem_debug_pop(void)291*5b10f583Schristos int CRYPTO_mem_debug_pop(void)
292*5b10f583Schristos {
293*5b10f583Schristos     return 0;
294*5b10f583Schristos }
295*5b10f583Schristos 
CRYPTO_mem_debug_malloc(void * addr,size_t num,int flag,const char * file,int line)296*5b10f583Schristos void CRYPTO_mem_debug_malloc(void *addr, size_t num, int flag,
297*5b10f583Schristos                              const char *file, int line)
298*5b10f583Schristos {
299*5b10f583Schristos     (void)addr; (void)num; (void)flag; (void)file; (void)line;
300*5b10f583Schristos }
301*5b10f583Schristos 
CRYPTO_mem_debug_realloc(void * addr1,void * addr2,size_t num,int flag,const char * file,int line)302*5b10f583Schristos void CRYPTO_mem_debug_realloc(void *addr1, void *addr2, size_t num, int flag,
303*5b10f583Schristos                               const char *file, int line)
304*5b10f583Schristos {
305*5b10f583Schristos     (void)addr1; (void)addr2; (void)num; (void)flag; (void)file; (void)line;
306*5b10f583Schristos }
307*5b10f583Schristos 
CRYPTO_mem_debug_free(void * addr,int flag,const char * file,int line)308*5b10f583Schristos void CRYPTO_mem_debug_free(void *addr, int flag,
309*5b10f583Schristos                            const char *file, int line)
310*5b10f583Schristos {
311*5b10f583Schristos     (void)addr; (void)flag; (void)file; (void)line;
312*5b10f583Schristos }
313*5b10f583Schristos 
CRYPTO_mem_leaks(BIO * b)314*5b10f583Schristos int CRYPTO_mem_leaks(BIO *b)
315*5b10f583Schristos {
316*5b10f583Schristos     (void)b;
317*5b10f583Schristos     return -1;
318*5b10f583Schristos }
319*5b10f583Schristos 
320*5b10f583Schristos #  ifndef OPENSSL_NO_STDIO
CRYPTO_mem_leaks_fp(FILE * fp)321*5b10f583Schristos int CRYPTO_mem_leaks_fp(FILE *fp)
322*5b10f583Schristos {
323*5b10f583Schristos     (void)fp;
324*5b10f583Schristos     return -1;
325*5b10f583Schristos }
326*5b10f583Schristos #  endif
327*5b10f583Schristos 
CRYPTO_mem_leaks_cb(int (* cb)(const char * str,size_t len,void * u),void * u)328*5b10f583Schristos int CRYPTO_mem_leaks_cb(int (*cb)(const char *str, size_t len, void *u),
329*5b10f583Schristos                         void *u)
330*5b10f583Schristos {
331*5b10f583Schristos     (void)cb; (void)u;
332*5b10f583Schristos     return -1;
333*5b10f583Schristos }
334*5b10f583Schristos 
335*5b10f583Schristos # endif
336*5b10f583Schristos 
337*5b10f583Schristos #endif
338