From 58a15ae04e597d6ab353f00a3ee72260c0b6f802 Mon Sep 17 00:00:00 2001 From: Prashanth Pai Date: Wed, 12 Jul 2017 12:59:35 +0530 Subject: socket: call init_openssl_mt() in init() and add cleanup init_openssl_mt() wasn't explicitly invoked and was run implicitly before dlopen() returned as it was tagged as __attribute__ ((constructor)). This function used to call GF_CALLOC() which wasn't available or initialized when socket.so is dlopen()ed by an external program. The program used to crash with SIGSEGV as follows: 0x00007ffff5efe1ad in __gf_calloc (nmemb=41, size=40, type=158, typestr=0x7ffff63eb3d6 "gf_sock_mt_lock_array") at mem-pool.c:109 0x00007ffff63e6acf in init_openssl_mt () at socket.c:4016 0x00007ffff7de90da in call_init.part () from /lib64/ld-linux-x86-64.so.2 0x00007ffff7de91eb in _dl_init () from /lib64/ld-linux-x86-64.so.2 0x00007ffff7dedde1 in dl_open_worker () from /lib64/ld-linux-x86-64.so.2 0x00007ffff7de8f84 in _dl_catch_error () from /lib64/ld-linux-x86-64.so.2 0x00007ffff7ded339 in _dl_open () from /lib64/ld-linux-x86-64.so.2 This change moves call to init_openssl_mt() from being a constructor function to the init() function and introduces fini_openssl_mt() which cleans up resources (called in destructor). BUG: 1193929 Change-Id: Iab690897ec34e24c33f6b43f8d8d9f8fd75ac607 Signed-off-by: Prashanth Pai Reviewed-on: https://review.gluster.org/17753 Smoke: Gluster Build System CentOS-regression: Gluster Build System Reviewed-by: Amar Tumballi Reviewed-by: Jeff Darcy --- rpc/rpc-transport/socket/src/socket.c | 64 +++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 25 deletions(-) (limited to 'rpc/rpc-transport/socket/src/socket.c') diff --git a/rpc/rpc-transport/socket/src/socket.c b/rpc/rpc-transport/socket/src/socket.c index dd7f5d3b77e..02a0a86526a 100644 --- a/rpc/rpc-transport/socket/src/socket.c +++ b/rpc/rpc-transport/socket/src/socket.c @@ -3962,15 +3962,7 @@ out: } -/* - * Unlike the stuff in init, this only needs to be called once GLOBALLY no - * matter how many translators/sockets we end up with. Conveniently, - * __attribute__(constructor) provides exactly those semantics in a pretty - * portable fashion. - */ - static pthread_mutex_t *lock_array = NULL; -static gf_boolean_t constructor_ok = _gf_false; static void locking_func (int mode, int type, const char *file, int line) @@ -4007,29 +3999,61 @@ legacy_threadid_func (void) } #endif -static void __attribute__((constructor)) +static void init_openssl_mt (void) { int num_locks = CRYPTO_num_locks(); int i; + if (lock_array) { + /* this only needs to be initialized once GLOBALLY no + matter how many translators/sockets we end up with. */ + return; + } + + SSL_library_init(); + SSL_load_error_strings(); + lock_array = GF_CALLOC (num_locks, sizeof(pthread_mutex_t), gf_sock_mt_lock_array); if (lock_array) { for (i = 0; i < num_locks; ++i) { pthread_mutex_init (&lock_array[i], NULL); } - CRYPTO_set_locking_callback (locking_func); #if HAVE_CRYPTO_THREADID CRYPTO_THREADID_set_callback (threadid_func); #else /* older openssl */ CRYPTO_set_id_callback (legacy_threadid_func); #endif - constructor_ok = _gf_true; + CRYPTO_set_locking_callback (locking_func); } - SSL_library_init(); - SSL_load_error_strings(); +} + +static void __attribute__((destructor)) +fini_openssl_mt (void) +{ + int i; + + if (!lock_array) { + return; + } + + CRYPTO_set_locking_callback(NULL); +#if HAVE_CRYPTO_THREADID + CRYPTO_THREADID_set_callback (NULL); +#else /* older openssl */ + CRYPTO_set_id_callback (NULL); +#endif + + for (i = 0; i < CRYPTO_num_locks(); ++i) { + pthread_mutex_destroy (&lock_array[i]); + } + + GF_FREE (lock_array); + lock_array = NULL; + + ERR_free_strings(); } static void @@ -4319,18 +4343,6 @@ socket_init (rpc_transport_t *this) if (priv->ssl_enabled || priv->mgmt_ssl) { BIO *bio = NULL; - /* - * The right time to check this is after all of our relevant - * fields have been set, but before we start issuing OpenSSL - * calls for the current translator. In other words, now. - */ - if (!constructor_ok) { - gf_log (this->name, GF_LOG_ERROR, - "can't initialize TLS socket (%s)", - "static constructor failed"); - goto err; - } - #if HAVE_TLSV1_2_METHOD priv->ssl_meth = (SSL_METHOD *)TLSv1_2_method(); #else @@ -4548,6 +4560,8 @@ init (rpc_transport_t *this) { int ret = -1; + init_openssl_mt(); + ret = socket_init (this); if (ret == -1) { -- cgit