I used memory debug functions (such as CRYPTO_mem_leaks/CRYPTO_mem_leaks_fp) to 
check the memory leak. In the old version, such as openssl-1.0.2d, I can call 
CRYPTO_mem_leaks() functions any time in my application to dump the memory 
information. But in OpenSSL-1.1.0, it will fail due to the new 
CRYPTO_mem_leaks() introduce the RUN_ONCE() function to initialize the memory 
lock and cleanup the locks at the end of the function.
My application is a multi-process application, parent process will perform the 
memory lock initialization once, so in child process the RUN_ONCE() function 
will never be performed. After I perform CRYPTO_mem_leaks(), at the end of this 
function, the malloc_lock will be freed, so it will cause unexpected coredump 
if I insert CRYPTO_mem_leaks() function in my code. What I can do now is 
register this function to atexit(), when the process exit, CRYPTO_mem_leaks() 
will be performed to dump the memory leakage information.
Is this behavior expected?

int CRYPTO_mem_leaks(BIO *b)
{
    MEM_LEAK ml;

    /*
     * OPENSSL_cleanup() will free the ex_data locks so we can't have any
     * ex_data hanging around
     */
    bio_free_ex_data(b);

    /* Ensure all resources are released */
    OPENSSL_cleanup();

    if (!RUN_ONCE(&memdbg_init, do_memdbg_init))
        return -1;

    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE);

    ml.bio = b;
    ml.bytes = 0;
    ml.chunks = 0;
    if (mh != NULL)
        lh_MEM_doall_MEM_LEAK(mh, print_leak, &ml);

    if (ml.chunks != 0) {
        BIO_printf(b, "%ld bytes leaked in %d chunks\n", ml.bytes, ml.chunks);
    } else {
        /*
         * Make sure that, if we found no leaks, memory-leak debugging itself
         * does not introduce memory leaks (which might irritate external
         * debugging tools). (When someone enables leak checking, but does not
         * call this function, we declare it to be their fault.)
         */
        int old_mh_mode;

        CRYPTO_THREAD_write_lock(malloc_lock);

        /*
         * avoid deadlock when lh_free() uses CRYPTO_mem_debug_free(), which 
uses
         * mem_check_on
         */
        old_mh_mode = mh_mode;
        mh_mode = CRYPTO_MEM_CHECK_OFF;

        lh_MEM_free(mh);
        mh = NULL;

        mh_mode = old_mh_mode;
        CRYPTO_THREAD_unlock(malloc_lock);
    }
    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);

    /* Clean up locks etc */
    CRYPTO_THREAD_cleanup_local(&appinfokey);
    CRYPTO_THREAD_lock_free(malloc_lock);
    CRYPTO_THREAD_lock_free(long_malloc_lock);
    malloc_lock = NULL;
    long_malloc_lock = NULL;

    return ml.chunks == 0 ? 1 : 0;
}


-- 
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users

Reply via email to