When doing a fork() and exec(), two problems existed (Issue 8086):

1) Ignored signals stayed ignored after the exec().
2) Signals could possibly fire between the fork() and exec(), causing Asterisk
signal handlers within the child to execute, which caused nasty race conditions.


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@48374 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.2
Tilghman Lesher 19 years ago
parent 611a9778bb
commit 983d09bc21

@ -31,6 +31,7 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
#include <signal.h>
#include "asterisk.h" #include "asterisk.h"
@ -258,9 +259,13 @@ static int app_exec(struct ast_channel *chan, void *data)
FILE *child_commands = NULL; FILE *child_commands = NULL;
FILE *child_errors = NULL; FILE *child_errors = NULL;
FILE *child_events = NULL; FILE *child_events = NULL;
sigset_t fullset, oldset;
LOCAL_USER_ADD(u); LOCAL_USER_ADD(u);
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
AST_LIST_HEAD_INIT(&u->playlist); AST_LIST_HEAD_INIT(&u->playlist);
AST_LIST_HEAD_INIT(&u->finishlist); AST_LIST_HEAD_INIT(&u->finishlist);
u->abort_current_sound = 0; u->abort_current_sound = 0;
@ -314,6 +319,9 @@ static int app_exec(struct ast_channel *chan, void *data)
/* child process */ /* child process */
int i; int i;
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
if (option_highpriority) if (option_highpriority)
ast_set_priority(0); ast_set_priority(0);
@ -337,6 +345,8 @@ static int app_exec(struct ast_channel *chan, void *data)
int waitfds[2] = { child_errors_fd, child_commands_fd }; int waitfds[2] = { child_errors_fd, child_commands_fd };
struct ast_channel *rchan; struct ast_channel *rchan;
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
close(child_stdin[0]); close(child_stdin[0]);
child_stdin[0] = 0; child_stdin[0] = 0;
close(child_stdout[1]); close(child_stdout[1]);

@ -127,19 +127,26 @@ static int send_waveform_to_fd(char *waveform, int length, int fd) {
#ifdef __PPC__ #ifdef __PPC__
char c; char c;
#endif #endif
sigset_t fullset, oldset;
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
res = fork(); res = fork();
if (res < 0) if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n"); ast_log(LOG_WARNING, "Fork failed\n");
if (res) if (res) {
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return res; return res;
}
for (x=0;x<256;x++) { for (x=0;x<256;x++) {
if (x != fd) if (x != fd)
close(x); close(x);
} }
if (option_highpriority) if (option_highpriority)
ast_set_priority(0); ast_set_priority(0);
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
/*IAS */ /*IAS */
#ifdef __PPC__ #ifdef __PPC__
for( x=0; x<length; x+=2) for( x=0; x<length; x+=2)

@ -68,15 +68,27 @@ static int icesencode(char *filename, int fd)
{ {
int res; int res;
int x; int x;
sigset_t fullset, oldset;
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
res = fork(); res = fork();
if (res < 0) if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n"); ast_log(LOG_WARNING, "Fork failed\n");
if (res) if (res) {
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return res; return res;
}
/* Stop ignoring PIPE */
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
if (option_highpriority) if (option_highpriority)
ast_set_priority(0); ast_set_priority(0);
dup2(fd, STDIN_FILENO); dup2(fd, STDIN_FILENO);
for (x=STDERR_FILENO + 1;x<256;x++) { for (x=STDERR_FILENO + 1;x<1024;x++) {
if ((x != STDIN_FILENO) && (x != STDOUT_FILENO)) if ((x != STDIN_FILENO) && (x != STDOUT_FILENO))
close(x); close(x);
} }
@ -87,7 +99,7 @@ static int icesencode(char *filename, int fd)
/* As a last-ditch effort, try to use PATH */ /* As a last-ditch effort, try to use PATH */
execlp("ices", "ices", filename, (char *)NULL); execlp("ices", "ices", filename, (char *)NULL);
ast_log(LOG_WARNING, "Execute of ices failed\n"); ast_log(LOG_WARNING, "Execute of ices failed\n");
return -1; _exit(0);
} }
static int ices_exec(struct ast_channel *chan, void *data) static int ices_exec(struct ast_channel *chan, void *data)

@ -67,15 +67,25 @@ static int mp3play(char *filename, int fd)
{ {
int res; int res;
int x; int x;
sigset_t fullset, oldset;
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
res = fork(); res = fork();
if (res < 0) if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n"); ast_log(LOG_WARNING, "Fork failed\n");
if (res) if (res) {
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return res; return res;
}
if (option_highpriority) if (option_highpriority)
ast_set_priority(0); ast_set_priority(0);
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
dup2(fd, STDOUT_FILENO); dup2(fd, STDOUT_FILENO);
for (x=0;x<256;x++) { for (x=STDERR_FILENO + 1;x<256;x++) {
if (x != STDOUT_FILENO) if (x != STDOUT_FILENO)
close(x); close(x);
} }
@ -97,7 +107,7 @@ static int mp3play(char *filename, int fd)
execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL); execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
} }
ast_log(LOG_WARNING, "Execute of mpg123 failed\n"); ast_log(LOG_WARNING, "Execute of mpg123 failed\n");
return -1; _exit(0);
} }
static int timed_read(int fd, void *data, int datalen, int timeout) static int timed_read(int fd, void *data, int datalen, int timeout)

@ -71,16 +71,26 @@ static int NBScatplay(int fd)
{ {
int res; int res;
int x; int x;
sigset_t fullset, oldset;
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
res = fork(); res = fork();
if (res < 0) if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n"); ast_log(LOG_WARNING, "Fork failed\n");
if (res) if (res) {
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return res; return res;
}
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
if (option_highpriority) if (option_highpriority)
ast_set_priority(0); ast_set_priority(0);
dup2(fd, STDOUT_FILENO); dup2(fd, STDOUT_FILENO);
for (x=0;x<256;x++) { for (x = STDERR_FILENO + 1; x < 1024; x++) {
if (x != STDOUT_FILENO) if (x != STDOUT_FILENO)
close(x); close(x);
} }
@ -88,7 +98,7 @@ static int NBScatplay(int fd)
execl(NBSCAT, "nbscat8k", "-d", (char *)NULL); execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL); execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
ast_log(LOG_WARNING, "Execute of nbscat8k failed\n"); ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
return -1; _exit(0);
} }
static int timed_read(int fd, void *data, int datalen) static int timed_read(int fd, void *data, int datalen)

@ -87,11 +87,23 @@ static pid_t spawn_ras(struct ast_channel *chan, char *args)
char *argv[PPP_MAX_ARGS]; char *argv[PPP_MAX_ARGS];
int argc = 0; int argc = 0;
char *stringp=NULL; char *stringp=NULL;
sigset_t fullset, oldset;
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
/* Start by forking */ /* Start by forking */
pid = fork(); pid = fork();
if (pid) if (pid) {
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return pid; return pid;
}
/* Restore original signal handlers */
for (x=0;x<NSIG;x++)
signal(x, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
/* Execute RAS on File handles */ /* Execute RAS on File handles */
dup2(chan->fds[0], STDIN_FILENO); dup2(chan->fds[0], STDIN_FILENO);
@ -104,10 +116,6 @@ static pid_t spawn_ras(struct ast_channel *chan, char *args)
for (x=STDERR_FILENO + 1;x<1024;x++) for (x=STDERR_FILENO + 1;x<1024;x++)
close(x); close(x);
/* Restore original signal handlers */
for (x=0;x<NSIG;x++)
signal(x, SIG_DFL);
/* Reset all arguments */ /* Reset all arguments */
memset(argv, 0, sizeof(argv)); memset(argv, 0, sizeof(argv));

@ -234,7 +234,7 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
int audio[2]; int audio[2];
int x; int x;
int res; int res;
sigset_t signal_set; sigset_t signal_set, old_set;
if (!strncasecmp(script, "agi://", 6)) if (!strncasecmp(script, "agi://", 6))
return launch_netscript(script, argv, fds, efd, opid); return launch_netscript(script, argv, fds, efd, opid);
@ -276,6 +276,10 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
return -1; return -1;
} }
} }
/* Block SIGHUP during the fork - prevents a race */
sigfillset(&signal_set);
pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno)); ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
@ -293,9 +297,18 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
} else { } else {
close(STDERR_FILENO + 1); close(STDERR_FILENO + 1);
} }
/* Before we unblock our signals, return our trapped signals back to the defaults */
signal(SIGHUP, SIG_DFL);
signal(SIGCHLD, SIG_DFL);
signal(SIGINT, SIG_DFL);
signal(SIGURG, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
signal(SIGXFSZ, SIG_DFL);
/* unblock important signal handlers */ /* unblock important signal handlers */
if (sigfillset(&signal_set) || pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) { if (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno)); ast_log(LOG_WARNING, "unable to unblock signals for AGI script: %s\n", strerror(errno));
_exit(1); _exit(1);
} }
@ -310,6 +323,7 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
fprintf(stderr, "Failed to execute '%s': %s\n", script, strerror(errno)); fprintf(stderr, "Failed to execute '%s': %s\n", script, strerror(errno));
_exit(1); _exit(1);
} }
pthread_sigmask(SIG_SETMASK, &old_set, NULL);
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script); ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script);
fds[0] = toast[0]; fds[0] = toast[0];

@ -326,6 +326,7 @@ static int spawn_mp3(struct mohclass *class)
int argc = 0; int argc = 0;
DIR *dir = NULL; DIR *dir = NULL;
struct dirent *de; struct dirent *de;
sigset_t signal_set, old_set;
if (!strcasecmp(class->dir, "nodir")) { if (!strcasecmp(class->dir, "nodir")) {
@ -426,6 +427,11 @@ static int spawn_mp3(struct mohclass *class)
if (time(NULL) - class->start < respawn_time) { if (time(NULL) - class->start < respawn_time) {
sleep(respawn_time - (time(NULL) - class->start)); sleep(respawn_time - (time(NULL) - class->start));
} }
/* Block signals during the fork() */
sigfillset(&signal_set);
pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
time(&class->start); time(&class->start);
class->pid = fork(); class->pid = fork();
if (class->pid < 0) { if (class->pid < 0) {
@ -440,6 +446,10 @@ static int spawn_mp3(struct mohclass *class)
if (option_highpriority) if (option_highpriority)
ast_set_priority(0); ast_set_priority(0);
/* Reset ignored signals back to default */
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL);
close(fds[0]); close(fds[0]);
/* Stdout goes to pipe */ /* Stdout goes to pipe */
dup2(fds[1], STDOUT_FILENO); dup2(fds[1], STDOUT_FILENO);
@ -466,6 +476,7 @@ static int spawn_mp3(struct mohclass *class)
_exit(1); _exit(1);
} else { } else {
/* Parent */ /* Parent */
pthread_sigmask(SIG_SETMASK, &old_set, NULL);
close(fds[1]); close(fds[1]);
} }
return fds[0]; return fds[0];

Loading…
Cancel
Save