mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-04 20:04:50 +00:00
CLI: Address multiple issues.
* listen uses the variable `s` for the result from ast_poll() then overwrites it with the result of accept(). Create a separate variable poll_result to avoid confusion since ast_poll does not return a file descriptor. * Resolve fd leak that would occur if setsockopt failed in listen. * Reserve an extra byte while processing completion results from remote daemon. This fixes a bug where completion processing used strstr() on a string that was not '\0' terminated. This was no risk to the Asterisk daemon, the bug was only reachable the remote console process. * Resolve leak in handle_showchan when the channel is not found. * Multiple leaks and a deadlock in pbx_config CLI completion. * Fix leaks in "manager show command". Change-Id: I8f633ceb1714867ae30ef4e421858f77c14485a9
This commit is contained in:
@@ -1573,17 +1573,21 @@ static void *listener(void *unused)
|
||||
int s;
|
||||
socklen_t len;
|
||||
int x;
|
||||
int poll_result;
|
||||
struct pollfd fds[1];
|
||||
|
||||
for (;;) {
|
||||
if (ast_socket < 0)
|
||||
if (ast_socket < 0) {
|
||||
return NULL;
|
||||
}
|
||||
fds[0].fd = ast_socket;
|
||||
fds[0].events = POLLIN;
|
||||
s = ast_poll(fds, 1, -1);
|
||||
poll_result = ast_poll(fds, 1, -1);
|
||||
pthread_testcancel();
|
||||
if (s < 0) {
|
||||
if (errno != EINTR)
|
||||
if (poll_result < 0) {
|
||||
if (errno != EINTR) {
|
||||
ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
len = sizeof(sunaddr);
|
||||
@@ -1597,6 +1601,7 @@ static void *listener(void *unused)
|
||||
/* turn on socket credentials passing. */
|
||||
if (setsockopt(s, SOL_SOCKET, SO_PASSCRED, &sckopt, sizeof(sckopt)) < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to turn on socket credentials passing\n");
|
||||
close(s);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -3051,20 +3056,10 @@ static char *cli_complete(EditLine *editline, int ch)
|
||||
#define CMD_MATCHESARRAY "_COMMAND MATCHESARRAY \"%s\" \"%s\""
|
||||
char *mbuf;
|
||||
char *new_mbuf;
|
||||
int mlen = 0, maxmbuf = 2048;
|
||||
int mlen = 0;
|
||||
int maxmbuf = ast_asprintf(&mbuf, CMD_MATCHESARRAY, lf->buffer, ptr);
|
||||
|
||||
/* Start with a 2048 byte buffer */
|
||||
mbuf = ast_malloc(maxmbuf);
|
||||
|
||||
/* This will run snprintf twice at most. */
|
||||
while (mbuf && (mlen = snprintf(mbuf, maxmbuf, CMD_MATCHESARRAY, lf->buffer, ptr)) > maxmbuf) {
|
||||
/* Return value does not include space for NULL terminator. */
|
||||
maxmbuf = mlen + 1;
|
||||
ast_free(mbuf);
|
||||
mbuf = ast_malloc(maxmbuf);
|
||||
}
|
||||
|
||||
if (!mbuf) {
|
||||
if (maxmbuf == -1) {
|
||||
*((char *) lf->cursor) = savechr;
|
||||
|
||||
return (char *)(CC_ERROR);
|
||||
@@ -3077,9 +3072,9 @@ static char *cli_complete(EditLine *editline, int ch)
|
||||
|
||||
while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
|
||||
if (mlen + 1024 > maxmbuf) {
|
||||
/* Expand buffer to the next 1024 byte increment. */
|
||||
/* Expand buffer to the next 1024 byte increment plus a NULL terminator. */
|
||||
maxmbuf = mlen + 1024;
|
||||
new_mbuf = ast_realloc(mbuf, maxmbuf);
|
||||
new_mbuf = ast_realloc(mbuf, maxmbuf + 1);
|
||||
if (!new_mbuf) {
|
||||
ast_free(mbuf);
|
||||
*((char *) lf->cursor) = savechr;
|
||||
@@ -3092,6 +3087,7 @@ static char *cli_complete(EditLine *editline, int ch)
|
||||
res = read(ast_consock, mbuf + mlen, 1024);
|
||||
if (res > 0) {
|
||||
mlen += res;
|
||||
mbuf[mlen] = '\0';
|
||||
}
|
||||
}
|
||||
mbuf[mlen] = '\0';
|
||||
|
13
main/cli.c
13
main/cli.c
@@ -1496,17 +1496,20 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
|
||||
return CLI_FAILURE;
|
||||
}
|
||||
|
||||
output = ast_str_create(8192);
|
||||
if (!output) {
|
||||
return CLI_FAILURE;
|
||||
}
|
||||
|
||||
chan = ast_channel_get_by_name(a->argv[3]);
|
||||
if (!chan) {
|
||||
ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
|
||||
|
||||
return CLI_SUCCESS;
|
||||
}
|
||||
|
||||
output = ast_str_create(8192);
|
||||
if (!output) {
|
||||
ast_channel_unref(chan);
|
||||
|
||||
return CLI_FAILURE;
|
||||
}
|
||||
|
||||
now = ast_tvnow();
|
||||
ast_channel_lock(chan);
|
||||
|
||||
|
@@ -2343,11 +2343,12 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_
|
||||
AST_RWLIST_UNLOCK(&actions);
|
||||
return ret;
|
||||
}
|
||||
authority = ast_str_alloca(MAX_AUTH_PERM_STRING);
|
||||
if (a->argc < 4) {
|
||||
return CLI_SHOWUSAGE;
|
||||
}
|
||||
|
||||
authority = ast_str_alloca(MAX_AUTH_PERM_STRING);
|
||||
|
||||
#ifdef AST_XML_DOCS
|
||||
/* setup the titles */
|
||||
term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
|
||||
@@ -2375,6 +2376,22 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_
|
||||
char *seealso = ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1);
|
||||
char *privilege = ast_xmldoc_printable(S_OR(auth_str, "Not available"), 1);
|
||||
char *responses = ast_xmldoc_printable("None", 1);
|
||||
|
||||
if (!syntax || !synopsis || !description || !arguments
|
||||
|| !seealso || !privilege || !responses) {
|
||||
ast_free(syntax);
|
||||
ast_free(synopsis);
|
||||
ast_free(description);
|
||||
ast_free(arguments);
|
||||
ast_free(seealso);
|
||||
ast_free(privilege);
|
||||
ast_free(responses);
|
||||
ast_cli(a->fd, "Allocation failure.\n");
|
||||
AST_RWLIST_UNLOCK(&actions);
|
||||
|
||||
return CLI_FAILURE;
|
||||
}
|
||||
|
||||
ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s",
|
||||
syntax_title, syntax,
|
||||
synopsis_title, synopsis,
|
||||
@@ -2402,6 +2419,14 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_
|
||||
ast_cli(a->fd, "Event: %s\n", cur->final_response->name);
|
||||
print_event_instance(a, cur->final_response);
|
||||
}
|
||||
|
||||
ast_free(syntax);
|
||||
ast_free(synopsis);
|
||||
ast_free(description);
|
||||
ast_free(arguments);
|
||||
ast_free(seealso);
|
||||
ast_free(privilege);
|
||||
ast_free(responses);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
@@ -322,8 +322,10 @@ static char *complete_dialplan_remove_include(struct ast_cli_args *a)
|
||||
while ( (nc = ast_walk_contexts(nc)) && nc != c && !already_served)
|
||||
already_served = lookup_ci(nc, i_name);
|
||||
|
||||
if (!already_served && ++which > a->n)
|
||||
if (!already_served && ++which > a->n) {
|
||||
res = ast_strdup(i_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ast_unlock_context(c);
|
||||
}
|
||||
@@ -1549,17 +1551,21 @@ static char *complete_dialplan_remove_ignorepat(struct ast_cli_args *a)
|
||||
}
|
||||
|
||||
for (c = NULL; !ret && (c = ast_walk_contexts(c)); ) {
|
||||
if (ast_rdlock_context(c)) /* fail, skip it */
|
||||
if (ast_rdlock_context(c)) {
|
||||
/* fail, skip it */
|
||||
continue;
|
||||
if (!partial_match(ast_get_context_name(c), a->word, len))
|
||||
}
|
||||
if (!partial_match(ast_get_context_name(c), a->word, len)) {
|
||||
ast_unlock_context(c);
|
||||
continue;
|
||||
}
|
||||
if (lookup_c_ip(c, ignorepat) && ++which > a->n)
|
||||
ret = ast_strdup(ast_get_context_name(c));
|
||||
ast_unlock_context(c);
|
||||
}
|
||||
ast_unlock_contexts();
|
||||
ast_free(dupline);
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
Reference in New Issue
Block a user