]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
When doing a fork() and exec(), two problems existed (Issue 8086):
authorTilghman Lesher <tilghman@meg.abyt.es>
Mon, 11 Dec 2006 00:33:59 +0000 (00:33 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Mon, 11 Dec 2006 00:33:59 +0000 (00:33 +0000)
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

apps/app_externalivr.c
apps/app_festival.c
apps/app_ices.c
apps/app_mp3.c
apps/app_nbscat.c
apps/app_zapras.c
res/res_agi.c
res/res_musiconhold.c

index fc5f34082f1c242e5cbc1740efeb818e32ed2944..068463cec1c3e76b1f346eb2fbd9db2558299a40 100644 (file)
@@ -31,6 +31,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
+#include <signal.h>
 
 #include "asterisk.h"
 
@@ -258,9 +259,13 @@ static int app_exec(struct ast_channel *chan, void *data)
        FILE *child_commands = NULL;
        FILE *child_errors = NULL;
        FILE *child_events = NULL;
+       sigset_t fullset, oldset;
 
        LOCAL_USER_ADD(u);
-       
+
+       sigfillset(&fullset);
+       pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
        AST_LIST_HEAD_INIT(&u->playlist);
        AST_LIST_HEAD_INIT(&u->finishlist);
        u->abort_current_sound = 0;
@@ -314,6 +319,9 @@ static int app_exec(struct ast_channel *chan, void *data)
                /* child process */
                int i;
 
+               signal(SIGPIPE, SIG_DFL);
+               pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+
                if (option_highpriority)
                        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 };
                struct ast_channel *rchan;
 
+               pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+
                close(child_stdin[0]);
                child_stdin[0] = 0;
                close(child_stdout[1]);
index 7c69dc8b981d9395f188ec863b887c2037004e4e..33f54aaf382e54c8c422428dde31fc50f4bab73b 100644 (file)
@@ -127,19 +127,26 @@ static int send_waveform_to_fd(char *waveform, int length, int fd) {
 #ifdef __PPC__ 
        char c;
 #endif
+       sigset_t fullset, oldset;
+
+       sigfillset(&fullset);
+       pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
 
         res = fork();
         if (res < 0)
                 ast_log(LOG_WARNING, "Fork failed\n");
-        if (res)
+        if (res) {
+               pthread_sigmask(SIG_SETMASK, &oldset, NULL);
                 return res;
+       }
         for (x=0;x<256;x++) {
                 if (x != fd)
                         close(x);
         }
        if (option_highpriority)
                ast_set_priority(0);
-
+       signal(SIGPIPE, SIG_DFL);
+       pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
 /*IAS */
 #ifdef __PPC__  
        for( x=0; x<length; x+=2)
index b6b5ad3f7634cda668e6d1210a46dbce9a2483c3..5a9b9412dd137c4f2ed457ed5f6730de56470eea 100644 (file)
@@ -68,15 +68,27 @@ static int icesencode(char *filename, int fd)
 {
        int res;
        int x;
+       sigset_t fullset, oldset;
+
+       sigfillset(&fullset);
+       pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
        res = fork();
        if (res < 0) 
                ast_log(LOG_WARNING, "Fork failed\n");
-       if (res)
+       if (res) {
+               pthread_sigmask(SIG_SETMASK, &oldset, NULL);
                return res;
+       }
+
+       /* Stop ignoring PIPE */
+       signal(SIGPIPE, SIG_DFL);
+       pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+
        if (option_highpriority)
                ast_set_priority(0);
        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))
                        close(x);
        }
@@ -87,7 +99,7 @@ static int icesencode(char *filename, int fd)
        /* As a last-ditch effort, try to use PATH */
        execlp("ices", "ices", filename, (char *)NULL);
        ast_log(LOG_WARNING, "Execute of ices failed\n");
-       return -1;
+       _exit(0);
 }
 
 static int ices_exec(struct ast_channel *chan, void *data)
index 31fc3209635253d25ceb27964a40e11a46c9db6b..1cba886bbe0b02f6503a678f62db09b32270769f 100644 (file)
@@ -67,15 +67,25 @@ static int mp3play(char *filename, int fd)
 {
        int res;
        int x;
+       sigset_t fullset, oldset;
+
+       sigfillset(&fullset);
+       pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
        res = fork();
        if (res < 0) 
                ast_log(LOG_WARNING, "Fork failed\n");
-       if (res)
+       if (res) {
+               pthread_sigmask(SIG_SETMASK, &oldset, NULL);
                return res;
+       }
        if (option_highpriority)
                ast_set_priority(0);
+       signal(SIGPIPE, SIG_DFL);
+       pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+
        dup2(fd, STDOUT_FILENO);
-       for (x=0;x<256;x++) {
+       for (x=STDERR_FILENO + 1;x<256;x++) {
                if (x != STDOUT_FILENO)
                        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);
        }
        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)
index adc232373e50b63d541fe361c2490de7c359a043..004bde77bc920306b7e7316da125f11ddb02a3f6 100644 (file)
@@ -71,16 +71,26 @@ static int NBScatplay(int fd)
 {
        int res;
        int x;
+       sigset_t fullset, oldset;
+
+       sigfillset(&fullset);
+       pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
+
        res = fork();
        if (res < 0) 
                ast_log(LOG_WARNING, "Fork failed\n");
-       if (res)
+       if (res) {
+               pthread_sigmask(SIG_SETMASK, &oldset, NULL);
                return res;
+       }
+       signal(SIGPIPE, SIG_DFL);
+       pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
+
        if (option_highpriority)
                ast_set_priority(0);
 
        dup2(fd, STDOUT_FILENO);
-       for (x=0;x<256;x++) {
+       for (x = STDERR_FILENO + 1; x < 1024; x++) {
                if (x != STDOUT_FILENO)
                        close(x);
        }
@@ -88,7 +98,7 @@ static int NBScatplay(int fd)
        execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
        execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
        ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
-       return -1;
+       _exit(0);
 }
 
 static int timed_read(int fd, void *data, int datalen)
index cf770f2b7950cd4bdf65742dbb09270fc56e1426..91336f5e4dbca5b3ec039b15b98695f39ae35e3e 100644 (file)
@@ -87,11 +87,23 @@ static pid_t spawn_ras(struct ast_channel *chan, char *args)
        char *argv[PPP_MAX_ARGS];
        int argc = 0;
        char *stringp=NULL;
+       sigset_t fullset, oldset;
+
+       sigfillset(&fullset);
+       pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
 
        /* Start by forking */
        pid = fork();
-       if (pid)
+       if (pid) {
+               pthread_sigmask(SIG_SETMASK, &oldset, NULL);
                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 */
        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++) 
                close(x);
 
-       /* Restore original signal handlers */
-       for (x=0;x<NSIG;x++)
-               signal(x, SIG_DFL);
-
        /* Reset all arguments */
        memset(argv, 0, sizeof(argv));
 
index 022cee46ea2570d3726e8c9d086aec370210eb7a..1d39c69362fb1a2adb9b6307a620d24eb4c6b497 100644 (file)
@@ -234,7 +234,7 @@ static int launch_script(char *script, char *argv[], int *fds, int *efd, int *op
        int audio[2];
        int x;
        int res;
-       sigset_t signal_set;
+       sigset_t signal_set, old_set;
        
        if (!strncasecmp(script, "agi://", 6))
                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;
                }
        }
+
+       /* Block SIGHUP during the fork - prevents a race */
+       sigfillset(&signal_set);
+       pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
        pid = fork();
        if (pid < 0) {
                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 {
                        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 */
-               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));
                        _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));
                _exit(1);
        }
+       pthread_sigmask(SIG_SETMASK, &old_set, NULL);
        if (option_verbose > 2) 
                ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script);
        fds[0] = toast[0];
index c7f1fff6a27df966fcf8d12ac310b6b6399e4389..746fa2d061326a58fd7df52a09d1c6d93cc899ed 100644 (file)
@@ -326,6 +326,7 @@ static int spawn_mp3(struct mohclass *class)
        int argc = 0;
        DIR *dir = NULL;
        struct dirent *de;
+       sigset_t signal_set, old_set;
 
        
        if (!strcasecmp(class->dir, "nodir")) {
@@ -426,6 +427,11 @@ static int spawn_mp3(struct mohclass *class)
        if (time(NULL) - class->start < respawn_time) {
                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);
        class->pid = fork();
        if (class->pid < 0) {
@@ -440,6 +446,10 @@ static int spawn_mp3(struct mohclass *class)
                if (option_highpriority)
                        ast_set_priority(0);
 
+               /* Reset ignored signals back to default */
+               signal(SIGPIPE, SIG_DFL);
+               pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL);
+
                close(fds[0]);
                /* Stdout goes to pipe */
                dup2(fds[1], STDOUT_FILENO);
@@ -466,6 +476,7 @@ static int spawn_mp3(struct mohclass *class)
                _exit(1);
        } else {
                /* Parent */
+               pthread_sigmask(SIG_SETMASK, &old_set, NULL);
                close(fds[1]);
        }
        return fds[0];