openssl: Fix (harmless) memory leaks at exit.
authorAndre Noll <maan@tuebingen.mpg.de>
Wed, 11 Sep 2019 20:12:32 +0000 (22:12 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Sat, 29 Feb 2020 16:00:07 +0000 (17:00 +0100)
Without this, valgrind --leak-check=full --show-leak-kinds=all
complains about four memory blocks reachable at exit, see below.

The first leak is fixed by the new call to ERR_remove_thread_state(),
which frees the error queue of the current thread. To squash the
other three, the call to EVP_cleanup() is needed to remove all of
openssl's internal ciphers and digests.

To make this work on both openssl-1.0 and for openssl-1.1, we need
to add additional header checks for configure.

---
==2818== 12 bytes in 1 blocks are still reachable in loss record 1 of 4
==2818==    at 0x40355EE: malloc (vg_replace_malloc.c:309)
==2818==    by 0x41B887C: CRYPTO_malloc (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x42459B7: lh_insert (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x4248542: int_thread_set_item (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x4249920: ERR_get_state (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x424A255: ERR_put_error (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x4222EF6: RSA_padding_check_PKCS1_OAEP_mgf1 (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x422306A: RSA_padding_check_PKCS1_OAEP (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x421F921: RSA_eay_private_decrypt (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x804F2E9: apc_priv_decrypt (openssl.c:206)
==2818==    by 0x804DB59: client_post_select (client_common.c:321)
==2818==    by 0x804CC57: call_post_select (sched.c:80)
==2818==    by 0x804CC57: sched_post_select (sched.c:106)
==2818==    by 0x804CC57: schedule (sched.c:159)
==2818==
==2818== 64 bytes in 1 blocks are still reachable in loss record 2 of 4
==2818==    at 0x40355EE: malloc (vg_replace_malloc.c:309)
==2818==    by 0x41B887C: CRYPTO_malloc (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x4245643: lh_new (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x424811F: int_thread_get (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x4248511: int_thread_set_item (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x4249920: ERR_get_state (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x424A255: ERR_put_error (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x4222EF6: RSA_padding_check_PKCS1_OAEP_mgf1 (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x422306A: RSA_padding_check_PKCS1_OAEP (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x421F921: RSA_eay_private_decrypt (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x804F2E9: apc_priv_decrypt (openssl.c:206)
==2818==    by 0x804DB59: client_post_select (client_common.c:321)
==2818==
==2818== 96 bytes in 1 blocks are still reachable in loss record 3 of 4
==2818==    at 0x40355EE: malloc (vg_replace_malloc.c:309)
==2818==    by 0x41B887C: CRYPTO_malloc (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x4245628: lh_new (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x424811F: int_thread_get (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x4248511: int_thread_set_item (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x4249920: ERR_get_state (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x424A255: ERR_put_error (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x4222EF6: RSA_padding_check_PKCS1_OAEP_mgf1 (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x422306A: RSA_padding_check_PKCS1_OAEP (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x421F921: RSA_eay_private_decrypt (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x804F2E9: apc_priv_decrypt (openssl.c:206)
==2818==    by 0x804DB59: client_post_select (client_common.c:321)
==2818==
==2818== 400 bytes in 1 blocks are still reachable in loss record 4 of 4
==2818==    at 0x40355EE: malloc (vg_replace_malloc.c:309)
==2818==    by 0x41B887C: CRYPTO_malloc (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x424988C: ERR_get_state (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x424A255: ERR_put_error (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x4222EF6: RSA_padding_check_PKCS1_OAEP_mgf1 (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x422306A: RSA_padding_check_PKCS1_OAEP (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x421F921: RSA_eay_private_decrypt (in /usr/local/lib/libcrypto.so.1.0.0)
==2818==    by 0x804F2E9: apc_priv_decrypt (openssl.c:206)
==2818==    by 0x804DB59: client_post_select (client_common.c:321)
==2818==    by 0x804CC57: call_post_select (sched.c:80)
==2818==    by 0x804CC57: sched_post_select (sched.c:106)
==2818==    by 0x804CC57: schedule (sched.c:159)
==2818==    by 0x804AB2D: main (client.c:656)

configure.ac
openssl.c

index d993e526c8a30bdab55da1dd5a9df6f1ead5b320..f518f89af154933ffaa64401ba1086b7e3f369c9 100644 (file)
@@ -114,6 +114,15 @@ if test $HAVE_OPENSSL = yes; then
        test $HAVE_CRYPTO_CLEANUP_ALL_EX_DATA = yes &&
                AC_DEFINE([HAVE_CRYPTO_CLEANUP_ALL_EX_DATA], [1],
                        [not available on FreeBSD 12])
        test $HAVE_CRYPTO_CLEANUP_ALL_EX_DATA = yes &&
                AC_DEFINE([HAVE_CRYPTO_CLEANUP_ALL_EX_DATA], [1],
                        [not available on FreeBSD 12])
+       HAVE_OPENSSL_THREAD_STOP=yes
+       AC_CHECK_DECL([OPENSSL_thread_stop], [],
+               [HAVE_OPENSSL_THREAD_STOP=no],
+               [#include <openssl/crypto.h>])
+       AC_CHECK_LIB([crypto], [OPENSSL_thread_stop], [],
+               [HAVE_OPENSSL_THREAD_STOP=no])
+       test $HAVE_OPENSSL_THREAD_STOP = yes &&
+               AC_DEFINE([HAVE_OPENSSL_THREAD_STOP], [1],
+                       [not available on openssl-1.0])
 fi
 UNSTASH_FLAGS
 ######################################################################### gcrypt
 fi
 UNSTASH_FLAGS
 ######################################################################### gcrypt
index 5f04c845c6ec1e8b5d837f827233df425033fad4..0ad9d7db4e7f035dce140365b2b38abc144b6923 100644 (file)
--- a/openssl.c
+++ b/openssl.c
@@ -60,6 +60,12 @@ void crypt_shutdown(void)
 #ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
        CRYPTO_cleanup_all_ex_data();
 #endif
 #ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA
        CRYPTO_cleanup_all_ex_data();
 #endif
+#ifdef HAVE_OPENSSL_THREAD_STOP /* openssl-1.1 or later */
+       OPENSSL_thread_stop();
+#else /* openssl-1.0 */
+       ERR_remove_thread_state(NULL);
+#endif
+       EVP_cleanup();
 }
 
 /*
 }
 
 /*