[Asterisk-code-review] pbx_ael: Fix possible crash and serious lockup issue regarding 'ael ... (asterisk[master])
Mark Murawski
asteriskteam at digium.com
Tue Aug 24 13:26:04 CDT 2021
Mark Murawski has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/16348 )
Change subject: pbx_ael: Fix possible crash and serious lockup issue regarding 'ael reload'
......................................................................
pbx_ael: Fix possible crash and serious lockup issue regarding 'ael reload'
Currently pbx_ael does not check if a reload is currently pending
before proceeding with a reload. This can cause multiple threads to
operate at the same time on what should be mutex protected data. This
change adds a reload mutex and prevents multiple reloads from occuring
simultaneously.
ASTERISK-29609 #close
Change-Id: I5ed392ad226f6e4e7696ad742076d3e45c57af35
---
M pbx/pbx_ael.c
1 file changed, 87 insertions(+), 3 deletions(-)
git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/48/16348/1
diff --git a/pbx/pbx_ael.c b/pbx/pbx_ael.c
index d55f2d4..608d30c 100644
--- a/pbx/pbx_ael.c
+++ b/pbx/pbx_ael.c
@@ -74,8 +74,21 @@
#define DEBUG_MACROS (1 << 2)
#define DEBUG_CONTEXTS (1 << 3)
+enum PBX_AEL_LOAD_RESULT {
+ PBX_AEL_LOAD_RESULT_SUCCESS = 0,
+ PBX_AEL_LOAD_RESULT_FAILED,
+ PBX_AEL_LOAD_RESULT_RELOAD_PENDING,
+};
+
+/*! Only allow one reload/unload action to take place at a given time */
+AST_MUTEX_DEFINE_STATIC(ael_load_lock);
+
static char *config = "extensions.ael";
static char *registrar = "pbx_ael";
+
+static int pbx_load_module_locked(void);
+static int pbx_load_module_wrapper_locked(void);
+static char *pbx_load_module_from_cli_locked(struct ast_cli_args *a);
static int pbx_load_module(void);
#ifndef AAL_ARGCHECK
@@ -143,6 +156,72 @@
/* if all the below are static, who cares if they are present? */
+/*!
+ \brief So that we can pass this result straight back to callers of load_module
+ \internal
+
+ \retval AST_MODULE_LOAD_SUCCESS Reload worked as intended
+ \retval AST_MODULE_LOAD_DECLINE Reload could not proceed. Either because of a syntax or other error in AEL or there's already a load in progress
+*/
+static int pbx_load_module_locked(void)
+{
+ int ret;
+
+ ret = pbx_load_module_wrapper_locked();
+
+ return (ret == PBX_AEL_LOAD_RESULT_SUCCESS) ? AST_MODULE_LOAD_SUCCESS : AST_MODULE_LOAD_DECLINE;
+}
+
+/*!
+ \brief Let function callers know exactly why the load failed
+ \internal
+
+ \retval PBX_AEL_LOAD_RESULT_SUCCESS Reload worked as intended
+ \retval PBX_AEL_LOAD_RESULT_FAILED Failed (typically due to syntax or other error in AEL files)
+ \retval PBX_AEL_LOAD_RESULT_RELOAD_PENDING Reload already in progress
+*/
+static int pbx_load_module_wrapper_locked(void)
+{
+ int ret;
+
+ if (ast_mutex_trylock(&ael_load_lock)) {
+ return PBX_AEL_LOAD_RESULT_RELOAD_PENDING;
+ };
+
+ ret = pbx_load_module();
+ ast_mutex_unlock(&ael_load_lock);
+
+ if (ret == AST_MODULE_LOAD_SUCCESS) {
+ return PBX_AEL_LOAD_RESULT_SUCCESS;
+ }
+
+ return PBX_AEL_LOAD_RESULT_FAILED;
+}
+
+/*!
+ \brief Give feedback to the original cli function caller about why the load failed
+ \internal
+
+ \retval CLI_SUCCESS Reload worked as intended
+ \retval CLI_FAILURE Reload could not proceed. Either because of a syntax or other error in AEL or there's already a load in progress
+*/
+static char *pbx_load_module_from_cli_locked(struct ast_cli_args *a)
+{
+ int ret;
+
+ ret = pbx_load_module_wrapper_locked();
+
+ if (ret == PBX_AEL_LOAD_RESULT_RELOAD_PENDING) {
+ ast_cli(a->fd, "A module reload request is already in progress; please be patient\n");
+ return CLI_FAILURE;
+ }
+
+ return (ret == PBX_AEL_LOAD_RESULT_SUCCESS) ? CLI_SUCCESS : CLI_FAILURE;
+}
+
+/*
+ Don't call this directly, always use pbx_load_module_locked
+*/
static int pbx_load_module(void)
{
int errs=0, sem_err=0, sem_warn=0, sem_note=0;
@@ -245,7 +324,7 @@
if (a->argc != 2)
return CLI_SHOWUSAGE;
- return (pbx_load_module() ? CLI_FAILURE : CLI_SUCCESS);
+ return (pbx_load_module_from_cli_locked(a) ? CLI_FAILURE : CLI_SUCCESS);
}
static struct ast_cli_entry cli_ael[] = {
@@ -255,11 +334,16 @@
static int unload_module(void)
{
+ ast_mutex_lock(&ael_load_lock);
ast_context_destroy(NULL, registrar);
ast_cli_unregister_multiple(cli_ael, ARRAY_LEN(cli_ael));
+
#ifndef STANDALONE
ast_unregister_application(aelsub);
#endif
+
+ ast_mutex_unlock(&ael_load_lock);
+
return 0;
}
@@ -269,12 +353,12 @@
#ifndef STANDALONE
ast_register_application_xml(aelsub, aelsub_exec);
#endif
- return (pbx_load_module());
+ return (pbx_load_module_locked());
}
static int reload(void)
{
- return pbx_load_module();
+ return pbx_load_module_locked();
}
#ifdef STANDALONE
--
To view, visit https://gerrit.asterisk.org/c/asterisk/+/16348
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: I5ed392ad226f6e4e7696ad742076d3e45c57af35
Gerrit-Change-Number: 16348
Gerrit-PatchSet: 1
Gerrit-Owner: Mark Murawski <markm at intellasoft.net>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20210824/aba35a80/attachment-0001.html>
More information about the asterisk-code-review
mailing list