]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
channelstorage_cpp_map_name_id: Add read locking around retrievals.
authorGeorge Joseph <gjoseph@sangoma.com>
Wed, 1 Oct 2025 14:30:52 +0000 (08:30 -0600)
committergithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Mon, 6 Oct 2025 13:50:31 +0000 (13:50 +0000)
When we retrieve a channel from a C++ map, we actually get back a wrapper
object that points to the channel then right after we retrieve it, we bump its
reference count.  There's a tiny chance however that between those two
statements a delete and/or unref might happen which would cause the wrapper
object or the channel itself to become invalid resulting in a SEGV.  To avoid
this we now perform a read lock on the driver around those statements.

Resolves: #1491

main/channelstorage_cpp_map_name_id.cc

index a8ff3828148d436e1335a17a9ee21f12754d3c35..cb9e00311a83ac12971d6822cee2fbb5b98d2652 100644 (file)
@@ -141,7 +141,17 @@ static int delete_channel(struct ast_channelstorage_instance *driver,
 /*! \brief returns number of active/allocated channels */
 static int active_channels(struct ast_channelstorage_instance *driver)
 {
-       return driver ? getdb(driver).size() : 0;
+       int count = 0;
+
+       if (!driver) {
+               return 0;
+       }
+
+       rdlock(driver);
+       count = getdb(driver).size();
+       unlock(driver);
+
+       return count;
 }
 
 static struct ast_channel *callback(struct ast_channelstorage_instance *driver,
@@ -454,14 +464,17 @@ static struct ast_channel *get_by_uniqueid(struct ast_channelstorage_instance *d
 {
        struct ast_channel *chan = NULL;
        char *search = uniqueid ? ast_str_to_lower(ast_strdupa(uniqueid)) : NULL;
+
        if (ast_strlen_zero(uniqueid)) {
                return NULL;
        }
 
+       rdlock(driver);
        auto rtn = map_by_id(driver).find(search);
        if (rtn != map_by_id(driver).end()) {
                chan = ao2_bump((struct ast_channel *)rtn->second);
        }
+       unlock(driver);
 
        return chan;
 }
@@ -469,16 +482,21 @@ static struct ast_channel *get_by_uniqueid(struct ast_channelstorage_instance *d
 static struct ast_channel *get_by_name_exact(struct ast_channelstorage_instance *driver,
        const char *name)
 {
+       struct ast_channel *chan = NULL;
        char *search = name ? ast_str_to_lower(ast_strdupa(name)) : NULL;
+
        if (ast_strlen_zero(name)) {
                return NULL;
        }
-       auto chan = getdb(driver).find(search);
-       if (chan != getdb(driver).end()) {
-               return ao2_bump((struct ast_channel *)chan->second);
+
+       rdlock(driver);
+       auto rtn = getdb(driver).find(search);
+       if (rtn != getdb(driver).end()) {
+               chan = ao2_bump((struct ast_channel *)rtn->second);
        }
+       unlock(driver);
 
-       return NULL;
+       return chan;
 }
 
 static struct ast_channel *get_by_name_prefix(struct ast_channelstorage_instance *driver,
@@ -493,10 +511,14 @@ static struct ast_channel *get_by_name_prefix(struct ast_channelstorage_instance
        }
 
        l_name = ast_str_to_lower(ast_strdupa(name));
+
+       rdlock(driver);
        auto rtn = getdb(driver).lower_bound(l_name);
        if (rtn != getdb(driver).end()) {
                chan = ao2_bump((struct ast_channel *)rtn->second);
        }
+       unlock(driver);
+
        return chan;
 }