diff options
author | Prashanth Pai <ppai@redhat.com> | 2017-07-12 12:59:35 +0530 |
---|---|---|
committer | Jeff Darcy <jeff@pl.atyp.us> | 2017-07-17 17:09:05 +0000 |
commit | 58a15ae04e597d6ab353f00a3ee72260c0b6f802 (patch) | |
tree | 9dd4b18af322adb558620a5dc75399265797cda9 /rpc/rpc-transport | |
parent | 4c410a46ef58512ba751db8750910a6d09ec3696 (diff) |
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 <ppai@redhat.com>
Reviewed-on: https://review.gluster.org/17753
Smoke: Gluster Build System <jenkins@build.gluster.org>
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
Reviewed-by: Amar Tumballi <amarts@redhat.com>
Reviewed-by: Jeff Darcy <jeff@pl.atyp.us>
Diffstat (limited to 'rpc/rpc-transport')
-rw-r--r-- | rpc/rpc-transport/socket/src/socket.c | 64 |
1 files changed, 39 insertions, 25 deletions
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) { |