channelstorage_cpp_map_name_id: Add read locking around retrievals.

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
This commit is contained in:
George Joseph
2025-10-01 08:30:52 -06:00
parent bce37d3b2f
commit bbb9f5ead5

View 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);
}
return NULL;
rdlock(driver);
auto rtn = getdb(driver).find(search);
if (rtn != getdb(driver).end()) {
chan = ao2_bump((struct ast_channel *)rtn->second);
}
unlock(driver);
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;
}