From: Jaco Kroon Date: Sat, 22 May 2021 12:42:04 +0000 (+0200) Subject: func_lock: Fix memory corruption during unload. X-Git-Tag: 18.5.0-rc1~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a3df5d7de81621e3c885c1a6863cb12be1648b64;p=thirdparty%2Fasterisk.git func_lock: Fix memory corruption during unload. AST_TRAVERSE accessess current as current = current->(field).next ... and since we free current (and ast_free poisons the memory) we either end up on a ast_mutex_lock to a non-existing lock that can never be obtained, or a segfault. Incidentally add logging in the "we have to wait for a lock to release" case, and remove an ineffective statement that sets memory that was just cleared by ast_calloc to zero. Change-Id: Id19ba3d9867b23d0e6783b97e6ecd8e62698b8c3 Signed-off-by: Jaco Kroon --- diff --git a/funcs/func_lock.c b/funcs/func_lock.c index ad4d58ef8b..f64011ffb6 100644 --- a/funcs/func_lock.c +++ b/funcs/func_lock.c @@ -249,7 +249,6 @@ static int get_lock(struct ast_channel *chan, char *lockname, int trylock) AST_LIST_UNLOCK(&locklist); return -1; } - current->requesters = 0; AST_LIST_INSERT_TAIL(&locklist, current, entries); } /* Add to requester list */ @@ -449,9 +448,16 @@ static int unload_module(void) ast_custom_function_unregister(&trylock_function); AST_LIST_LOCK(&locklist); - AST_LIST_TRAVERSE(&locklist, current, entries) { + while ((current = AST_LIST_REMOVE_HEAD(&locklist, entries))) { + int warned = 0; ast_mutex_lock(¤t->mutex); while (current->owner || current->requesters) { + if (!warned) { + ast_log(LOG_WARNING, "Waiting for %d requesters for %s lock %s.\n", + current->requesters, current->owner ? "locked" : "unlocked", + current->name); + warned = 1; + } /* either the mutex is locked, or other parties are currently in get_lock, * we need to wait for all of those to clear first */ ast_cond_wait(¤t->cond, ¤t->mutex);