Home | History | Annotate | Line # | Download | only in crypto
      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 <stdio.h>
     11 #include <stdlib.h>
     12 #include <time.h>
     13 #include "internal/cryptlib.h"
     14 #include "internal/thread_once.h"
     15 #include <openssl/crypto.h>
     16 #include <openssl/buffer.h>
     17 #include "internal/bio.h"
     18 #include <openssl/lhash.h>
     19 
     20 #ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
     21 # include <execinfo.h>
     22 #endif
     23 
     24 /*
     25  * The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE when
     26  * the application asks for it (usually after library initialisation for
     27  * which no book-keeping is desired). State CRYPTO_MEM_CHECK_ON exists only
     28  * temporarily when the library thinks that certain allocations should not be
     29  * checked (e.g. the data structures used for memory checking).  It is not
     30  * suitable as an initial state: the library will unexpectedly enable memory
     31  * checking when it executes one of those sections that want to disable
     32  * checking temporarily. State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes
     33  * no sense whatsoever.
     34  */
     35 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     36 static int mh_mode = CRYPTO_MEM_CHECK_OFF;
     37 #endif
     38 
     39 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
     40 static unsigned long order = 0; /* number of memory requests */
     41 
     42 /*-
     43  * For application-defined information (static C-string `info')
     44  * to be displayed in memory leak list.
     45  * Each thread has its own stack.  For applications, there is
     46  *   OPENSSL_mem_debug_push("...")     to push an entry,
     47  *   OPENSSL_mem_debug_pop()     to pop an entry,
     48  */
     49 struct app_mem_info_st {
     50     CRYPTO_THREAD_ID threadid;
     51     const char *file;
     52     int line;
     53     const char *info;
     54     struct app_mem_info_st *next; /* tail of thread's stack */
     55     int references;
     56 };
     57 
     58 static CRYPTO_ONCE memdbg_init = CRYPTO_ONCE_STATIC_INIT;
     59 CRYPTO_RWLOCK *memdbg_lock;
     60 static CRYPTO_RWLOCK *long_memdbg_lock;
     61 static CRYPTO_THREAD_LOCAL appinfokey;
     62 
     63 /* memory-block description */
     64 struct mem_st {
     65     void *addr;
     66     int num;
     67     const char *file;
     68     int line;
     69     CRYPTO_THREAD_ID threadid;
     70     unsigned long order;
     71     time_t time;
     72     APP_INFO *app_info;
     73 #ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
     74     void *array[30];
     75     size_t array_siz;
     76 #endif
     77 };
     78 
     79 /*
     80  * hash-table of memory requests (address as * key); access requires
     81  * long_memdbg_lock lock
     82  */
     83 static LHASH_OF(MEM) *mh = NULL;
     84 
     85 /* num_disable > 0 iff mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) */
     86 static unsigned int num_disable = 0;
     87 
     88 /*
     89  * Valid iff num_disable > 0.  long_memdbg_lock is locked exactly in this
     90  * case (by the thread named in disabling_thread).
     91  */
     92 static CRYPTO_THREAD_ID disabling_threadid;
     93 
     94 DEFINE_RUN_ONCE_STATIC(do_memdbg_init)
     95 {
     96     memdbg_lock = CRYPTO_THREAD_lock_new();
     97     long_memdbg_lock = CRYPTO_THREAD_lock_new();
     98     if (memdbg_lock == NULL || long_memdbg_lock == NULL
     99         || !CRYPTO_THREAD_init_local(&appinfokey, NULL)) {
    100         CRYPTO_THREAD_lock_free(memdbg_lock);
    101         memdbg_lock = NULL;
    102         CRYPTO_THREAD_lock_free(long_memdbg_lock);
    103         long_memdbg_lock = NULL;
    104         return 0;
    105     }
    106     return 1;
    107 }
    108 
    109 static void app_info_free(APP_INFO *inf)
    110 {
    111     if (inf == NULL)
    112         return;
    113     if (--(inf->references) <= 0) {
    114         app_info_free(inf->next);
    115         OPENSSL_free(inf);
    116     }
    117 }
    118 #endif
    119 
    120 int CRYPTO_mem_ctrl(int mode)
    121 {
    122 #ifdef OPENSSL_NO_CRYPTO_MDEBUG
    123     return mode - mode;
    124 #else
    125     int ret = mh_mode;
    126 
    127     if (!RUN_ONCE(&memdbg_init, do_memdbg_init))
    128         return -1;
    129 
    130     CRYPTO_THREAD_write_lock(memdbg_lock);
    131     switch (mode) {
    132     default:
    133         break;
    134 
    135     case CRYPTO_MEM_CHECK_ON:
    136         mh_mode = CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE;
    137         num_disable = 0;
    138         break;
    139 
    140     case CRYPTO_MEM_CHECK_OFF:
    141         mh_mode = 0;
    142         num_disable = 0;
    143         break;
    144 
    145     /* switch off temporarily (for library-internal use): */
    146     case CRYPTO_MEM_CHECK_DISABLE:
    147         if (mh_mode & CRYPTO_MEM_CHECK_ON) {
    148             CRYPTO_THREAD_ID cur = CRYPTO_THREAD_get_current_id();
    149             /* see if we don't have long_memdbg_lock already */
    150             if (!num_disable
    151                 || !CRYPTO_THREAD_compare_id(disabling_threadid, cur)) {
    152                 /*
    153                  * Long-time lock long_memdbg_lock must not be claimed
    154                  * while we're holding memdbg_lock, or we'll deadlock
    155                  * if somebody else holds long_memdbg_lock (and cannot
    156                  * release it because we block entry to this function). Give
    157                  * them a chance, first, and then claim the locks in
    158                  * appropriate order (long-time lock first).
    159                  */
    160                 CRYPTO_THREAD_unlock(memdbg_lock);
    161                 /*
    162                  * Note that after we have waited for long_memdbg_lock and
    163                  * memdbg_lock, we'll still be in the right "case" and
    164                  * "if" branch because MemCheck_start and MemCheck_stop may
    165                  * never be used while there are multiple OpenSSL threads.
    166                  */
    167                 CRYPTO_THREAD_write_lock(long_memdbg_lock);
    168                 CRYPTO_THREAD_write_lock(memdbg_lock);
    169                 mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
    170                 disabling_threadid = cur;
    171             }
    172             num_disable++;
    173         }
    174         break;
    175 
    176     case CRYPTO_MEM_CHECK_ENABLE:
    177         if (mh_mode & CRYPTO_MEM_CHECK_ON) {
    178             if (num_disable) {  /* always true, or something is going wrong */
    179                 num_disable--;
    180                 if (num_disable == 0) {
    181                     mh_mode |= CRYPTO_MEM_CHECK_ENABLE;
    182                     CRYPTO_THREAD_unlock(long_memdbg_lock);
    183                 }
    184             }
    185         }
    186         break;
    187     }
    188     CRYPTO_THREAD_unlock(memdbg_lock);
    189     return ret;
    190 #endif
    191 }
    192 
    193 #ifndef OPENSSL_NO_CRYPTO_MDEBUG
    194 
    195 static int mem_check_on(void)
    196 {
    197     int ret = 0;
    198     CRYPTO_THREAD_ID cur;
    199 
    200     if (mh_mode & CRYPTO_MEM_CHECK_ON) {
    201         if (!RUN_ONCE(&memdbg_init, do_memdbg_init))
    202             return 0;
    203 
    204         cur = CRYPTO_THREAD_get_current_id();
    205         CRYPTO_THREAD_read_lock(memdbg_lock);
    206 
    207         ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
    208             || !CRYPTO_THREAD_compare_id(disabling_threadid, cur);
    209 
    210         CRYPTO_THREAD_unlock(memdbg_lock);
    211     }
    212     return ret;
    213 }
    214 
    215 static int mem_cmp(const MEM *a, const MEM *b)
    216 {
    217 #ifdef _WIN64
    218     const char *ap = (const char *)a->addr, *bp = (const char *)b->addr;
    219     if (ap == bp)
    220         return 0;
    221     else if (ap > bp)
    222         return 1;
    223     else
    224         return -1;
    225 #else
    226     return (const char *)a->addr - (const char *)b->addr;
    227 #endif
    228 }
    229 
    230 static unsigned long mem_hash(const MEM *a)
    231 {
    232     size_t ret;
    233 
    234     ret = (size_t)a->addr;
    235 
    236     ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251;
    237     return ret;
    238 }
    239 
    240 /* returns 1 if there was an info to pop, 0 if the stack was empty. */
    241 static int pop_info(void)
    242 {
    243     APP_INFO *current = NULL;
    244 
    245     if (!RUN_ONCE(&memdbg_init, do_memdbg_init))
    246         return 0;
    247 
    248     current = (APP_INFO *)CRYPTO_THREAD_get_local(&appinfokey);
    249     if (current != NULL) {
    250         APP_INFO *next = current->next;
    251 
    252         if (next != NULL) {
    253             next->references++;
    254             CRYPTO_THREAD_set_local(&appinfokey, next);
    255         } else {
    256             CRYPTO_THREAD_set_local(&appinfokey, NULL);
    257         }
    258         if (--(current->references) <= 0) {
    259             current->next = NULL;
    260             if (next != NULL)
    261                 next->references--;
    262             OPENSSL_free(current);
    263         }
    264         return 1;
    265     }
    266     return 0;
    267 }
    268 
    269 int CRYPTO_mem_debug_push(const char *info, const char *file, int line)
    270 {
    271     APP_INFO *ami, *amim;
    272     int ret = 0;
    273 
    274     if (mem_check_on()) {
    275         CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
    276 
    277         if (!RUN_ONCE(&memdbg_init, do_memdbg_init)
    278             || (ami = OPENSSL_malloc(sizeof(*ami))) == NULL)
    279             goto err;
    280 
    281         ami->threadid = CRYPTO_THREAD_get_current_id();
    282         ami->file = file;
    283         ami->line = line;
    284         ami->info = info;
    285         ami->references = 1;
    286         ami->next = NULL;
    287 
    288         amim = (APP_INFO *)CRYPTO_THREAD_get_local(&appinfokey);
    289         CRYPTO_THREAD_set_local(&appinfokey, ami);
    290 
    291         if (amim != NULL)
    292             ami->next = amim;
    293         ret = 1;
    294  err:
    295         CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
    296     }
    297 
    298     return ret;
    299 }
    300 
    301 int CRYPTO_mem_debug_pop(void)
    302 {
    303     int ret = 0;
    304 
    305     if (mem_check_on()) {
    306         CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
    307         ret = pop_info();
    308         CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
    309     }
    310     return ret;
    311 }
    312 
    313 static unsigned long break_order_num = 0;
    314 
    315 void CRYPTO_mem_debug_malloc(void *addr, size_t num, int before_p,
    316                              const char *file, int line)
    317 {
    318     MEM *m, *mm;
    319     APP_INFO *amim;
    320 
    321     switch (before_p & 127) {
    322     case 0:
    323         break;
    324     case 1:
    325         if (addr == NULL)
    326             break;
    327 
    328         if (mem_check_on()) {
    329             CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
    330 
    331             if (!RUN_ONCE(&memdbg_init, do_memdbg_init)
    332                 || (m = OPENSSL_malloc(sizeof(*m))) == NULL) {
    333                 OPENSSL_free(addr);
    334                 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
    335                 return;
    336             }
    337             if (mh == NULL) {
    338                 if ((mh = lh_MEM_new(mem_hash, mem_cmp)) == NULL) {
    339                     OPENSSL_free(addr);
    340                     OPENSSL_free(m);
    341                     addr = NULL;
    342                     goto err;
    343                 }
    344             }
    345 
    346             m->addr = addr;
    347             m->file = file;
    348             m->line = line;
    349             m->num = num;
    350             m->threadid = CRYPTO_THREAD_get_current_id();
    351 
    352             if (order == break_order_num) {
    353                 /* BREAK HERE */
    354                 m->order = order;
    355             }
    356             m->order = order++;
    357 # ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
    358             m->array_siz = backtrace(m->array, OSSL_NELEM(m->array));
    359 # endif
    360             m->time = time(NULL);
    361 
    362             amim = (APP_INFO *)CRYPTO_THREAD_get_local(&appinfokey);
    363             m->app_info = amim;
    364             if (amim != NULL)
    365                 amim->references++;
    366 
    367             if ((mm = lh_MEM_insert(mh, m)) != NULL) {
    368                 /* Not good, but don't sweat it */
    369                 if (mm->app_info != NULL) {
    370                     mm->app_info->references--;
    371                 }
    372                 OPENSSL_free(mm);
    373             }
    374  err:
    375             CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
    376         }
    377         break;
    378     }
    379     return;
    380 }
    381 
    382 void CRYPTO_mem_debug_free(void *addr, int before_p,
    383         const char *file, int line)
    384 {
    385     MEM m, *mp;
    386 
    387     switch (before_p) {
    388     case 0:
    389         if (addr == NULL)
    390             break;
    391 
    392         if (mem_check_on() && (mh != NULL)) {
    393             CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
    394 
    395             m.addr = addr;
    396             mp = lh_MEM_delete(mh, &m);
    397             if (mp != NULL) {
    398                 app_info_free(mp->app_info);
    399                 OPENSSL_free(mp);
    400             }
    401 
    402             CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
    403         }
    404         break;
    405     case 1:
    406         break;
    407     }
    408 }
    409 
    410 void CRYPTO_mem_debug_realloc(void *addr1, void *addr2, size_t num,
    411                               int before_p, const char *file, int line)
    412 {
    413     MEM m, *mp;
    414 
    415     switch (before_p) {
    416     case 0:
    417         break;
    418     case 1:
    419         if (addr2 == NULL)
    420             break;
    421 
    422         if (addr1 == NULL) {
    423             CRYPTO_mem_debug_malloc(addr2, num, 128 | before_p, file, line);
    424             break;
    425         }
    426 
    427         if (mem_check_on()) {
    428             CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
    429 
    430             m.addr = addr1;
    431             mp = lh_MEM_delete(mh, &m);
    432             if (mp != NULL) {
    433                 mp->addr = addr2;
    434                 mp->num = num;
    435 #ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
    436                 mp->array_siz = backtrace(mp->array, OSSL_NELEM(mp->array));
    437 #endif
    438                 (void)lh_MEM_insert(mh, mp);
    439             }
    440 
    441             CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
    442         }
    443         break;
    444     }
    445     return;
    446 }
    447 
    448 typedef struct mem_leak_st {
    449     int (*print_cb) (const char *str, size_t len, void *u);
    450     void *print_cb_arg;
    451     int chunks;
    452     long bytes;
    453 } MEM_LEAK;
    454 
    455 static void print_leak(const MEM *m, MEM_LEAK *l)
    456 {
    457     char buf[1024];
    458     char *bufp = buf;
    459     size_t len = sizeof(buf), ami_cnt;
    460     APP_INFO *amip;
    461     int n;
    462     struct tm *lcl = NULL;
    463     /*
    464      * Convert between CRYPTO_THREAD_ID (which could be anything at all) and
    465      * a long. This may not be meaningful depending on what CRYPTO_THREAD_ID is
    466      * but hopefully should give something sensible on most platforms
    467      */
    468     union {
    469         CRYPTO_THREAD_ID tid;
    470         unsigned long ltid;
    471     } tid;
    472     CRYPTO_THREAD_ID ti;
    473 
    474     lcl = localtime(&m->time);
    475     n = BIO_snprintf(bufp, len, "[%02d:%02d:%02d] ",
    476                      lcl->tm_hour, lcl->tm_min, lcl->tm_sec);
    477     if (n <= 0) {
    478         bufp[0] = '\0';
    479         return;
    480     }
    481     bufp += n;
    482     len -= n;
    483 
    484     n = BIO_snprintf(bufp, len, "%5lu file=%s, line=%d, ",
    485                      m->order, m->file, m->line);
    486     if (n <= 0)
    487         return;
    488     bufp += n;
    489     len -= n;
    490 
    491     tid.ltid = 0;
    492     tid.tid = m->threadid;
    493     n = BIO_snprintf(bufp, len, "thread=%lu, ", tid.ltid);
    494     if (n <= 0)
    495         return;
    496     bufp += n;
    497     len -= n;
    498 
    499     n = BIO_snprintf(bufp, len, "number=%d, address=%p\n", m->num, m->addr);
    500     if (n <= 0)
    501         return;
    502     bufp += n;
    503     len -= n;
    504 
    505     l->print_cb(buf, (size_t)(bufp - buf), l->print_cb_arg);
    506 
    507     l->chunks++;
    508     l->bytes += m->num;
    509 
    510     amip = m->app_info;
    511     ami_cnt = 0;
    512 
    513     if (amip) {
    514         ti = amip->threadid;
    515 
    516         do {
    517             int buf_len;
    518             int info_len;
    519 
    520             ami_cnt++;
    521             if (ami_cnt >= sizeof(buf) - 1)
    522                 break;
    523             memset(buf, '>', ami_cnt);
    524             buf[ami_cnt] = '\0';
    525             tid.ltid = 0;
    526             tid.tid = amip->threadid;
    527             n = BIO_snprintf(buf + ami_cnt, sizeof(buf) - ami_cnt,
    528                              " thread=%lu, file=%s, line=%d, info=\"",
    529                              tid.ltid, amip->file, amip->line);
    530             if (n <= 0)
    531                 break;
    532             buf_len = ami_cnt + n;
    533             info_len = strlen(amip->info);
    534             if (128 - buf_len - 3 < info_len) {
    535                 memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
    536                 buf_len = 128 - 3;
    537             } else {
    538                 n = BIO_snprintf(buf + buf_len, sizeof(buf) - buf_len, "%s",
    539                                  amip->info);
    540                 if (n < 0)
    541                     break;
    542                 buf_len += n;
    543             }
    544             n = BIO_snprintf(buf + buf_len, sizeof(buf) - buf_len, "\"\n");
    545             if (n <= 0)
    546                 break;
    547 
    548             l->print_cb(buf, buf_len + n, l->print_cb_arg);
    549 
    550             amip = amip->next;
    551         }
    552         while (amip && CRYPTO_THREAD_compare_id(amip->threadid, ti));
    553     }
    554 
    555 #ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
    556     {
    557         size_t i;
    558         char **strings = backtrace_symbols(m->array, m->array_siz);
    559 
    560         for (i = 0; i < m->array_siz; i++)
    561             fprintf(stderr, "##> %s\n", strings[i]);
    562         free(strings);
    563     }
    564 #endif
    565 }
    566 
    567 IMPLEMENT_LHASH_DOALL_ARG_CONST(MEM, MEM_LEAK);
    568 
    569 int CRYPTO_mem_leaks_cb(int (*cb) (const char *str, size_t len, void *u),
    570                         void *u)
    571 {
    572     MEM_LEAK ml;
    573 
    574     /* Ensure all resources are released */
    575     OPENSSL_cleanup();
    576 
    577     if (!RUN_ONCE(&memdbg_init, do_memdbg_init))
    578         return -1;
    579 
    580     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
    581 
    582     ml.print_cb = cb;
    583     ml.print_cb_arg = u;
    584     ml.bytes = 0;
    585     ml.chunks = 0;
    586     if (mh != NULL)
    587         lh_MEM_doall_MEM_LEAK(mh, print_leak, &ml);
    588 
    589     if (ml.chunks != 0) {
    590         char buf[256];
    591 
    592         BIO_snprintf(buf, sizeof(buf), "%ld bytes leaked in %d chunks\n",
    593                      ml.bytes, ml.chunks);
    594         cb(buf, strlen(buf), u);
    595     } else {
    596         /*
    597          * Make sure that, if we found no leaks, memory-leak debugging itself
    598          * does not introduce memory leaks (which might irritate external
    599          * debugging tools). (When someone enables leak checking, but does not
    600          * call this function, we declare it to be their fault.)
    601          */
    602         int old_mh_mode;
    603 
    604         CRYPTO_THREAD_write_lock(memdbg_lock);
    605 
    606         /*
    607          * avoid deadlock when lh_free() uses CRYPTO_mem_debug_free(), which uses
    608          * mem_check_on
    609          */
    610         old_mh_mode = mh_mode;
    611         mh_mode = CRYPTO_MEM_CHECK_OFF;
    612 
    613         lh_MEM_free(mh);
    614         mh = NULL;
    615 
    616         mh_mode = old_mh_mode;
    617         CRYPTO_THREAD_unlock(memdbg_lock);
    618     }
    619     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);
    620 
    621     /* Clean up locks etc */
    622     CRYPTO_THREAD_cleanup_local(&appinfokey);
    623     CRYPTO_THREAD_lock_free(memdbg_lock);
    624     CRYPTO_THREAD_lock_free(long_memdbg_lock);
    625     memdbg_lock = NULL;
    626     long_memdbg_lock = NULL;
    627 
    628     return ml.chunks == 0 ? 1 : 0;
    629 }
    630 
    631 static int print_bio(const char *str, size_t len, void *b)
    632 {
    633     return BIO_write((BIO *)b, str, len);
    634 }
    635 
    636 int CRYPTO_mem_leaks(BIO *b)
    637 {
    638     /*
    639      * OPENSSL_cleanup() will free the ex_data locks so we can't have any
    640      * ex_data hanging around
    641      */
    642     bio_free_ex_data(b);
    643 
    644     return CRYPTO_mem_leaks_cb(print_bio, b);
    645 }
    646 
    647 # ifndef OPENSSL_NO_STDIO
    648 int CRYPTO_mem_leaks_fp(FILE *fp)
    649 {
    650     BIO *b;
    651     int ret;
    652 
    653     /*
    654      * Need to turn off memory checking when allocated BIOs ... especially as
    655      * we're creating them at a time when we're trying to check we've not
    656      * left anything un-free()'d!!
    657      */
    658     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);
    659     b = BIO_new(BIO_s_file());
    660     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE);
    661     if (b == NULL)
    662         return -1;
    663     BIO_set_fp(b, fp, BIO_NOCLOSE);
    664     ret = CRYPTO_mem_leaks_cb(print_bio, b);
    665     BIO_free(b);
    666     return ret;
    667 }
    668 # endif
    669 
    670 #endif
    671