From fda036e79e9e49f15e238295a883807416d26feb Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Fri, 5 Jun 2020 12:51:28 +0300 Subject: libglusterfs: fix use-after-destroy mutex error Found with GCC ThreadSanitizer: WARNING: ThreadSanitizer: use of an invalid mutex (e.g. uninitialized or destroyed) (pid=188590) #0 pthread_mutex_lock (libtsan.so.0+0x528ac) #1 client_ctx_del /path/to/glusterfs/libglusterfs/src/client_t.c:535 (libglusterfs.so.0+0xc681a) #2 client_destroy_cbk /path/to/glusterfs/xlators/protocol/server/src/server.c:944 (server.so+0xaf6e) #3 gf_client_destroy_recursive /path/to/glusterfs/libglusterfs/src/client_t.c:295 (libglusterfs.so.0+0xc5058) #4 client_destroy /path/to/glusterfs/libglusterfs/src/client_t.c:330 (libglusterfs.so.0+0xc60e4) ... Location is heap block of size 272 at 0x7b440001a180 allocated by thread T7: #0 calloc (libtsan.so.0+0x3075a) #1 __gf_calloc /path/to/glusterfs/libglusterfs/src/mem-pool.c:151 (libglusterfs.so.0+0x6e42b) #2 gf_client_get /path/to/glusterfs/libglusterfs/src/client_t.c:155 (libglusterfs.so.0+0xc571a) ... The problem is that client_destroy() may call client_ctx_del() (which attempts to lock 'sratch_ctx.lock') via recursive deletion from gf_client_destroy_recursive(), so destroying mutex before entering recursive deletion is an error. It should be destroyed later - just before the client context is freed. Change-Id: I730a628714d2b404e3f019ae552403da16b51b68 Signed-off-by: Dmitry Antipov Fixes: #1285 --- libglusterfs/src/client_t.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libglusterfs/src/client_t.c b/libglusterfs/src/client_t.c index 4cd22f4920c..9d377c3c2e1 100644 --- a/libglusterfs/src/client_t.c +++ b/libglusterfs/src/client_t.c @@ -314,8 +314,6 @@ client_destroy(client_t *client) clienttable = client->this->ctx->clienttable; - LOCK_DESTROY(&client->scratch_ctx.lock); - LOCK(&clienttable->lock); { clienttable->cliententries[client->tbl_index].client = NULL; @@ -333,6 +331,8 @@ client_destroy(client_t *client) if (client->subdir_inode) inode_unref(client->subdir_inode); + LOCK_DESTROY(&client->scratch_ctx.lock); + GF_FREE(client->auth.data); GF_FREE(client->auth.username); GF_FREE(client->auth.passwd); -- cgit