]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
func_lock: Fix memory corruption during unload.
authorJaco Kroon <jaco@uls.co.za>
Sat, 22 May 2021 12:42:04 +0000 (14:42 +0200)
committerFriendly Automation <jenkins2@gerrit.asterisk.org>
Fri, 11 Jun 2021 17:37:18 +0000 (12:37 -0500)
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 <jaco@uls.co.za>
funcs/func_lock.c

index ad4d58ef8bc37e5281ec4e79b68d9ff2e6bf406a..f64011ffb6eef0490820a3b637f3a352191cb29d 100644 (file)
@@ -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(&current->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(&current->cond, &current->mutex);