openssl: RAND_DRBG does not free related pointers

RAND_DRBG is not freeing pointers created before and linked into RAND_DRBG* like EVP_CIPHERs.

void RAND_DRBG_free(RAND_DRBG *drbg)
{
    if (drbg == NULL)
        return;

    if (drbg->meth != NULL)
        drbg->meth->uninstantiate(drbg);
    rand_pool_free(drbg->adin_pool);
    CRYPTO_THREAD_lock_free(drbg->lock);
    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data);

    if (drbg->secure)
        OPENSSL_secure_clear_free(drbg, sizeof(*drbg));
    else
        OPENSSL_clear_free(drbg, sizeof(*drbg));
}

[16:13:30] 798 file=crypto/rand/rand_lib.c, line=444, thread=15072, number=12288, address=0x2610a830 [16:13:30] 787 file=crypto/rand/drbg_lib.c, line=191, thread=15072, number=360, address=0x261005d0 [16:13:30] 803 file=crypto/evp/evp_enc.c, line=42, thread=15072, number=160, address=0x2610d9b0 [16:13:30] 788 file=crypto/evp/evp_enc.c, line=42, thread=15072, number=160, address=0x26100740 [16:13:30] 813 file=crypto/rand/rand_lib.c, line=444, thread=15072, number=12288, address=0x2610fb20 [16:13:30] 804 file=crypto/evp/evp_enc.c, line=42, thread=15072, number=160, address=0x2610da60 [16:13:30] 790 file=crypto/evp/evp_enc.c, line=128, thread=15072, number=264, address=0x111d2f0 [16:13:30] 812 file=crypto/rand/rand_lib.c, line=433, thread=15072, number=56, address=0x2610de30 [16:13:30] 789 file=crypto/evp/evp_enc.c, line=42, thread=15072, number=160, address=0x2610a780 [16:13:30] 801 file=crypto/evp/evp_enc.c, line=128, thread=15072, number=264, address=0x111cfc0 [16:13:30] 797 file=crypto/rand/rand_lib.c, line=433, thread=15072, number=56, address=0x26108b50 [16:13:30] 805 file=crypto/evp/evp_enc.c, line=128, thread=15072, number=264, address=0x111cc90 [16:13:30] 822 file=crypto/evp/evp_enc.c, line=128, thread=15072, number=264, address=0x111c630 [16:13:30] 802 file=crypto/rand/drbg_lib.c, line=191, thread=15072, number=360, address=0x2610d840 27104 bytes leaked in 14 chunks

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Comments: 25 (9 by maintainers)

Most upvoted comments

Not quite.

It looks like all the cleanup keys off of this handfn parameter to ossl_init_thread_start. https://github.com/openssl/openssl/blob/master/crypto/rand/rand_lib.c#L725 https://github.com/openssl/openssl/blob/master/crypto/initthread.c#L346 Which is called in init_thread_stop. https://github.com/openssl/openssl/blob/master/crypto/initthread.c#L303

That’s called in a bunch of places, but I gather this is the important one: https://github.com/openssl/openssl/blob/master/crypto/initthread.c#L195C13-L209

On pthreads, the cleanup parameter to CRYPTO_THREAD_init_local is registered as a cleanup handler. https://github.com/openssl/openssl/blob/master/crypto/threads_pthread.c#L160

But the parameter is silently ignored on Windows. So, on Windows, OpenSSL will leak this state if nothing calls OPENSSL_thread_stop. https://github.com/openssl/openssl/blob/master/crypto/threads_win.c#L154

There’s a DLL_THREAD_DETACH handler here, which calls it: https://github.com/openssl/openssl/blob/master/crypto/dllmain.c#L38

But per the docs, it doesn’t work when OpenSSL is linked statically on Windows. In that case, OpenSSL currently makes it the application’s responsibility to call OPENSSL_thread_stop on exit of every thread where OpenSSL is used. This is sufficiently non-obvious that it’s probably worth calling out more prominently. https://www.openssl.org/docs/man3.0/man3/OPENSSL_thread_stop.html#NOTES

CRYPTO_THREAD_init_local is also public API, but I don’t see any documentation that its cleanup function doesn’t work.

(It is possible to register a destructor with the thread-locals on Windows that works with static linking. We do it in BoringSSL and Chromium. But it’s pretty gnarly. I believe the C++11 thread_local keyword ultimately keys off of that mechanism on Windows.)

I can confirm the same leak with openSSL 1.1.1f is still there: mem.c:198 CRYPTO_malloc() mem.c:230 CRYPTO_zalloc() evp_enc.c:128 EVP_CipherInit_ex() drbg_ctr.c:274 ctr_update() drbg_ctr.c:349 drbg_ctr_generate() drbg_lib.c:641 RAND_DRBG_generate() drbg_lib.c:682 RAND_DRBG_bytes() drbg_lib.c:971 drbg_bytes() rand_lib.c:939 RAND_bytes()