[asterisk-commits] file: branch 1.8 r407205 - /branches/1.8/res/res_clialiases.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Feb 3 20:19:24 CST 2014


Author: file
Date: Mon Feb  3 20:19:22 2014
New Revision: 407205

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=407205
Log:
res_clialiases: Fix crash when reloading and re-aliasing an alias that is in use.

The code assumed that unregistering the alias would always succeed while in
practice this is not actually true. A common case is the "reload" command itself.
If the cli_aliases.conf configuration file was changed and reload executed the
command would fail to unregister and ultimately point to freed memory.

The reload process now checks whether unregistering succeeded or not and if not
the old CLI alias is retained.

(closes issue ASTERISK-19773)
Reported by: Joel Vandal

(closes issue ASTERISK-22757)
Reported by: Gareth Blades

Modified:
    branches/1.8/res/res_clialiases.c

Modified: branches/1.8/res/res_clialiases.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.8/res/res_clialiases.c?view=diff&rev=407205&r1=407204&r2=407205
==============================================================================
--- branches/1.8/res/res_clialiases.c (original)
+++ branches/1.8/res/res_clialiases.c Mon Feb  3 20:19:22 2014
@@ -68,15 +68,25 @@
 	return (alias0->cli_entry.command == alias1->cli_entry.command ? CMP_MATCH | CMP_STOP : 0);
 }
 
-/*! \brief Destruction function used for aliases */
-static void alias_destroy(void *obj)
+/*! \brief Callback for unregistering an alias */
+static int alias_unregister_cb(void *obj, void *arg, int flags)
 {
 	struct cli_alias *alias = obj;
 
 	/* Unregister the CLI entry from the core */
 	ast_cli_unregister(&alias->cli_entry);
 
-	return;
+	/* We can determine if this worked or not by looking at the cli_entry itself */
+	return !alias->cli_entry.command ? CMP_MATCH : 0;
+}
+
+/*! \brief Callback for finding an alias based on name */
+static int alias_name_cb(void *obj, void *arg, int flags)
+{
+	struct cli_alias *alias = obj;
+	char *name = arg;
+
+	return !strcmp(alias->alias, name) ? CMP_MATCH | CMP_STOP : 0;
 }
 
 /*! \brief Function which passes through an aliased CLI command to the real one */
@@ -188,7 +198,7 @@
 
 	/* Destroy any existing CLI aliases */
 	if (reload) {
-		ao2_callback(cli_aliases, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
+		ao2_callback(cli_aliases, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, alias_unregister_cb, NULL);
 	}
 
 	for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
@@ -198,7 +208,16 @@
 		}
 		/* Read in those there CLI aliases */
 		for (v1 = ast_variable_browse(cfg, v->value); v1; v1 = v1->next) {
-			if (!(alias = ao2_alloc((sizeof(*alias) + strlen(v1->name) + strlen(v1->value) + 2), alias_destroy))) {
+			struct cli_alias *existing = ao2_callback(cli_aliases, 0, alias_name_cb, (char*)v1->name);
+
+			if (existing) {
+				ast_log(LOG_WARNING, "Alias '%s' could not be unregistered and has been retained\n",
+					existing->alias);
+				ao2_ref(existing, -1);
+				continue;
+			}
+
+			if (!(alias = ao2_alloc((sizeof(*alias) + strlen(v1->name) + strlen(v1->value) + 2), NULL))) {
 				continue;
 			}
 			alias->alias = ((char *) alias) + sizeof(*alias);
@@ -234,6 +253,13 @@
 /*! \brief Function called to unload the module */
 static int unload_module(void)
 {
+	ao2_callback(cli_aliases, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, alias_unregister_cb, NULL);
+
+	if (ao2_container_count(cli_aliases)) {
+		ast_log(LOG_ERROR, "Could not unregister all CLI aliases\n");
+		return -1;
+	}
+
 	ao2_ref(cli_aliases, -1);
 
 	ast_cli_unregister_multiple(cli_alias, ARRAY_LEN(cli_alias));




More information about the asterisk-commits mailing list