1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.]
57 /* ====================================================================
58 * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions
64 * 1. Redistributions of source code must retain the above copyright
65 * notice, this list of conditions and the following disclaimer.
67 * 2. Redistributions in binary form must reproduce the above copyright
68 * notice, this list of conditions and the following disclaimer in
69 * the documentation and/or other materials provided with the
72 * 3. All advertising materials mentioning features or use of this
73 * software must display the following acknowledgment:
74 * "This product includes software developed by the OpenSSL Project
75 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78 * endorse or promote products derived from this software without
79 * prior written permission. For written permission, please contact
80 * openssl-core@openssl.org.
82 * 5. Products derived from this software may not be called "OpenSSL"
83 * nor may "OpenSSL" appear in their names without prior written
84 * permission of the OpenSSL Project.
86 * 6. Redistributions of any form whatsoever must retain the following
88 * "This product includes software developed by the OpenSSL Project
89 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
95 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102 * OF THE POSSIBILITY OF SUCH DAMAGE.
103 * ====================================================================
105 * This product includes cryptographic software written by Eric Young
106 * (eay@cryptsoft.com). This product includes software written by Tim
107 * Hudson (tjh@cryptsoft.com).
114 #include "internal/cryptlib.h"
115 #include "internal/threads.h"
116 #include <openssl/crypto.h>
117 #include <openssl/buffer.h>
118 #include "internal/bio.h"
119 #include <openssl/lhash.h>
121 #ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
122 # include <execinfo.h>
126 * The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE when
127 * the application asks for it (usually after library initialisation for
128 * which no book-keeping is desired). State CRYPTO_MEM_CHECK_ON exists only
129 * temporarily when the library thinks that certain allocations should not be
130 * checked (e.g. the data structures used for memory checking). It is not
131 * suitable as an initial state: the library will unexpectedly enable memory
132 * checking when it executes one of those sections that want to disable
133 * checking temporarily. State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes
134 * no sense whatsoever.
136 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
137 static int mh_mode = CRYPTO_MEM_CHECK_OFF;
140 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
141 static unsigned long order = 0; /* number of memory requests */
144 * For application-defined information (static C-string `info')
145 * to be displayed in memory leak list.
146 * Each thread has its own stack. For applications, there is
147 * OPENSSL_mem_debug_push("...") to push an entry,
148 * OPENSSL_mem_debug_pop() to pop an entry,
150 struct app_mem_info_st {
151 CRYPTO_THREAD_ID threadid;
155 struct app_mem_info_st *next; /* tail of thread's stack */
159 static CRYPTO_ONCE memdbg_init = CRYPTO_ONCE_STATIC_INIT;
160 static CRYPTO_RWLOCK *malloc_lock = NULL;
161 static CRYPTO_RWLOCK *long_malloc_lock = NULL;
162 static CRYPTO_THREAD_LOCAL appinfokey;
164 /* memory-block description */
170 CRYPTO_THREAD_ID threadid;
174 #ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
180 static LHASH_OF(MEM) *mh = NULL; /* hash-table of memory requests (address as
181 * key); access requires MALLOC2 lock */
183 /* num_disable > 0 iff mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) */
184 static unsigned int num_disable = 0;
187 * Valid iff num_disable > 0. long_malloc_lock is locked exactly in this
188 * case (by the thread named in disabling_thread).
190 static CRYPTO_THREAD_ID disabling_threadid;
192 static void do_memdbg_init(void)
194 malloc_lock = CRYPTO_THREAD_lock_new();
195 long_malloc_lock = CRYPTO_THREAD_lock_new();
196 CRYPTO_THREAD_init_local(&appinfokey, NULL);
199 static void app_info_free(APP_INFO *inf)
203 if (--(inf->references) <= 0) {
204 app_info_free(inf->next);
210 int CRYPTO_mem_ctrl(int mode)
212 #ifdef OPENSSL_NO_CRYPTO_MDEBUG
217 CRYPTO_THREAD_run_once(&memdbg_init, do_memdbg_init);
219 CRYPTO_THREAD_write_lock(malloc_lock);
224 case CRYPTO_MEM_CHECK_ON:
225 mh_mode = CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE;
229 case CRYPTO_MEM_CHECK_OFF:
234 /* switch off temporarily (for library-internal use): */
235 case CRYPTO_MEM_CHECK_DISABLE:
236 if (mh_mode & CRYPTO_MEM_CHECK_ON) {
237 CRYPTO_THREAD_ID cur = CRYPTO_THREAD_get_current_id();
238 /* see if we don't have long_malloc_lock already */
240 || !CRYPTO_THREAD_compare_id(disabling_threadid, cur)) {
242 * Long-time lock long_malloc_lock must not be claimed
243 * while we're holding malloc_lock, or we'll deadlock
244 * if somebody else holds long_malloc_lock (and cannot
245 * release it because we block entry to this function). Give
246 * them a chance, first, and then claim the locks in
247 * appropriate order (long-time lock first).
249 CRYPTO_THREAD_unlock(malloc_lock);
251 * Note that after we have waited for long_malloc_lock and
252 * malloc_lock, we'll still be in the right "case" and
253 * "if" branch because MemCheck_start and MemCheck_stop may
254 * never be used while there are multiple OpenSSL threads.
256 CRYPTO_THREAD_write_lock(long_malloc_lock);
257 CRYPTO_THREAD_write_lock(malloc_lock);
258 mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
259 disabling_threadid = cur;
265 case CRYPTO_MEM_CHECK_ENABLE:
266 if (mh_mode & CRYPTO_MEM_CHECK_ON) {
267 if (num_disable) { /* always true, or something is going wrong */
269 if (num_disable == 0) {
270 mh_mode |= CRYPTO_MEM_CHECK_ENABLE;
271 CRYPTO_THREAD_unlock(long_malloc_lock);
277 CRYPTO_THREAD_unlock(malloc_lock);
282 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
284 static int mem_check_on(void)
287 CRYPTO_THREAD_ID cur;
289 if (mh_mode & CRYPTO_MEM_CHECK_ON) {
290 CRYPTO_THREAD_run_once(&memdbg_init, do_memdbg_init);
292 cur = CRYPTO_THREAD_get_current_id();
293 CRYPTO_THREAD_read_lock(malloc_lock);
295 ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
296 || !CRYPTO_THREAD_compare_id(disabling_threadid, cur);
298 CRYPTO_THREAD_unlock(malloc_lock);
303 static int mem_cmp(const MEM *a, const MEM *b)
306 const char *ap = (const char *)a->addr, *bp = (const char *)b->addr;
314 return (const char *)a->addr - (const char *)b->addr;
318 static unsigned long mem_hash(const MEM *a)
322 ret = (size_t)a->addr;
324 ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251;
328 /* returns 1 if there was an info to pop, 0 if the stack was empty. */
329 static int pop_info(void)
331 APP_INFO *current = NULL;
333 CRYPTO_THREAD_run_once(&memdbg_init, do_memdbg_init);
334 current = (APP_INFO *)CRYPTO_THREAD_get_local(&appinfokey);
335 if (current != NULL) {
336 APP_INFO *next = current->next;
340 CRYPTO_THREAD_set_local(&appinfokey, next);
342 CRYPTO_THREAD_set_local(&appinfokey, NULL);
344 if (--(current->references) <= 0) {
345 current->next = NULL;
348 OPENSSL_free(current);
355 int CRYPTO_mem_debug_push(const char *info, const char *file, int line)
357 APP_INFO *ami, *amim;
360 if (mem_check_on()) {
361 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
363 CRYPTO_THREAD_run_once(&memdbg_init, do_memdbg_init);
365 if ((ami = OPENSSL_malloc(sizeof(*ami))) == NULL)
368 ami->threadid = CRYPTO_THREAD_get_current_id();
375 amim = (APP_INFO *)CRYPTO_THREAD_get_local(&appinfokey);
376 CRYPTO_THREAD_set_local(&appinfokey, ami);
382 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
388 int CRYPTO_mem_debug_pop(void)
392 if (mem_check_on()) {
393 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
395 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
400 static unsigned long break_order_num = 0;
402 void CRYPTO_mem_debug_malloc(void *addr, size_t num, int before_p,
403 const char *file, int line)
408 switch (before_p & 127) {
415 if (mem_check_on()) {
416 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
418 CRYPTO_THREAD_run_once(&memdbg_init, do_memdbg_init);
420 if ((m = OPENSSL_malloc(sizeof(*m))) == NULL) {
422 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
426 if ((mh = lh_MEM_new(mem_hash, mem_cmp)) == NULL) {
438 m->threadid = CRYPTO_THREAD_get_current_id();
440 if (order == break_order_num) {
445 # ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
446 m->array_siz = backtrace(m->array, OSSL_NELEM(m->array));
448 m->time = time(NULL);
450 amim = (APP_INFO *)CRYPTO_THREAD_get_local(&appinfokey);
455 if ((mm = lh_MEM_insert(mh, m)) != NULL) {
456 /* Not good, but don't sweat it */
457 if (mm->app_info != NULL) {
458 mm->app_info->references--;
463 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
470 void CRYPTO_mem_debug_free(void *addr, int before_p,
471 const char *file, int line)
480 if (mem_check_on() && (mh != NULL)) {
481 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
484 mp = lh_MEM_delete(mh, &m);
486 app_info_free(mp->app_info);
490 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
498 void CRYPTO_mem_debug_realloc(void *addr1, void *addr2, size_t num,
499 int before_p, const char *file, int line)
511 CRYPTO_mem_debug_malloc(addr2, num, 128 | before_p, file, line);
515 if (mem_check_on()) {
516 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
519 mp = lh_MEM_delete(mh, &m);
523 #ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
524 mp->array_siz = backtrace(mp->array, OSSL_NELEM(mp->array));
526 (void)lh_MEM_insert(mh, mp);
529 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
536 typedef struct mem_leak_st {
542 static void print_leak(const MEM *m, MEM_LEAK *l)
548 struct tm *lcl = NULL;
550 * Convert between CRYPTO_THREAD_ID (which could be anything at all) and
551 * a long. This may not be meaningful depending on what CRYPTO_THREAD_ID is
552 * but hopefully should give something sensible on most platforms
555 CRYPTO_THREAD_ID tid;
560 #define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
562 lcl = localtime(&m->time);
563 BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
564 lcl->tm_hour, lcl->tm_min, lcl->tm_sec);
565 bufp += strlen(bufp);
567 BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ",
568 m->order, m->file, m->line);
569 bufp += strlen(bufp);
572 tid.tid = m->threadid;
573 BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", tid.ltid);
574 bufp += strlen(bufp);
576 BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%p\n",
578 bufp += strlen(bufp);
580 BIO_puts(l->bio, buf);
596 memset(buf, '>', ami_cnt);
598 tid.tid = amip->threadid;
599 BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
600 " thread=%lu, file=%s, line=%d, info=\"",
601 tid.ltid, amip->file,
603 buf_len = strlen(buf);
604 info_len = strlen(amip->info);
605 if (128 - buf_len - 3 < info_len) {
606 memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
609 OPENSSL_strlcpy(buf + buf_len, amip->info, sizeof buf - buf_len);
610 buf_len = strlen(buf);
612 BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
614 BIO_puts(l->bio, buf);
618 while (amip && CRYPTO_THREAD_compare_id(amip->threadid, ti));
621 #ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
624 char **strings = backtrace_symbols(m->array, m->array_siz);
626 for (i = 0; i < m->array_siz; i++)
627 fprintf(stderr, "##> %s\n", strings[i]);
633 IMPLEMENT_LHASH_DOALL_ARG_CONST(MEM, MEM_LEAK);
635 int CRYPTO_mem_leaks(BIO *b)
640 * OPENSSL_cleanup() will free the ex_data locks so we can't have any
641 * ex_data hanging around
645 /* Ensure all resources are released */
648 CRYPTO_THREAD_run_once(&memdbg_init, do_memdbg_init);
650 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
656 lh_MEM_doall_MEM_LEAK(mh, print_leak, &ml);
658 if (ml.chunks != 0) {
659 BIO_printf(b, "%ld bytes leaked in %d chunks\n", ml.bytes, ml.chunks);
662 * Make sure that, if we found no leaks, memory-leak debugging itself
663 * does not introduce memory leaks (which might irritate external
664 * debugging tools). (When someone enables leak checking, but does not
665 * call this function, we declare it to be their fault.)
669 CRYPTO_THREAD_write_lock(malloc_lock);
672 * avoid deadlock when lh_free() uses CRYPTO_mem_debug_free(), which uses
675 old_mh_mode = mh_mode;
676 mh_mode = CRYPTO_MEM_CHECK_OFF;
681 mh_mode = old_mh_mode;
682 CRYPTO_THREAD_unlock(malloc_lock);
684 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);
686 /* Clean up locks etc */
687 CRYPTO_THREAD_cleanup_local(&appinfokey);
688 CRYPTO_THREAD_lock_free(malloc_lock);
689 CRYPTO_THREAD_lock_free(long_malloc_lock);
691 long_malloc_lock = NULL;
693 return ml.chunks == 0 ? 1 : 0;
696 # ifndef OPENSSL_NO_STDIO
697 int CRYPTO_mem_leaks_fp(FILE *fp)
703 * Need to turn off memory checking when allocated BIOs ... especially as
704 * we're creating them at a time when we're trying to check we've not
705 * left anything un-free()'d!!
707 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
708 b = BIO_new(BIO_s_file());
709 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
712 BIO_set_fp(b, fp, BIO_NOCLOSE);
713 ret = CRYPTO_mem_leaks(b);