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>
This commit is contained in:
parent
4c410a46ef
commit
58a15ae04e
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user