From: Roy Marples Date: Sat, 2 Feb 2008 19:17:08 +0000 (+0000) Subject: Block signals to avoid potential signal racing on BSD using fork. X-Git-Tag: v3.2.3~40 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=76ef136f1d0b2c1252da87a3c39e489e579f7eb0;p=thirdparty%2Fdhcpcd.git Block signals to avoid potential signal racing on BSD using fork. --- diff --git a/configure.c b/configure.c index 71282bb7..6372ee55 100644 --- a/configure.c +++ b/configure.c @@ -46,11 +46,14 @@ #include #ifndef BSD -#define HAVE_POSIX_SPAWN +# define HAVE_POSIX_SPAWN #endif #ifdef HAVE_POSIX_SPAWN -#include +# include +extern char **environ; +#else +# include #endif #include "config.h" @@ -65,7 +68,9 @@ #include "logger.h" #include "socket.h" -extern char **environ; +#ifndef HAVE_POSIX_SPAWN +#include "signal.h" +#endif static int file_in_path (const char *file) { @@ -103,6 +108,8 @@ static int exec_cmd (const char *cmd, const char *args, ...) int ret; #ifndef HAVE_POSIX_SPAWN pid_t pid; + sigset_t full; + sigset_t old; #endif va_start (va, args); @@ -128,15 +135,28 @@ static int exec_cmd (const char *cmd, const char *args, ...) ret = -1; } #else - if ((pid = vfork ()) == 0) { - if (execvp (cmd, argv) && errno != ENOENT) - logger (LOG_ERR, "error executing \"%s\": %s", - cmd, strerror (errno)); - _exit (0); - } else if (pid == -1) { - logger (LOG_ERR, "vfork: %s", strerror (errno)); - ret = -1; + /* OK, we need to block signals */ + sigfillset (&full); + sigprocmask (SIG_SETMASK, &full, &old); + + switch (pid = fork()) { + case -1: + logger (LOG_ERR, "vfork: %s", strerror (errno)); + ret = -1; + break; + case 0: + /* Reset signals and clear block */ + signal_reset (); + sigprocmask (SIG_SETMASK, &old, NULL); + if (execvp (cmd, argv) && errno != ENOENT) + logger (LOG_ERR, "error executing \"%s\": %s", + cmd, strerror (errno)); + _exit (0); + /* NOTREACHED */ } + + /* Restore our signals */ + sigprocmask (SIG_SETMASK, &old, NULL); #endif free (argv); diff --git a/signal.c b/signal.c index a61cb234..d38efb47 100644 --- a/signal.c +++ b/signal.c @@ -163,3 +163,21 @@ int signal_setup (void) return (0); } + +int signal_reset (void) +{ + struct sigaction sa; + unsigned int i; + + memset (&sa, 0, sizeof (sa)); + sa.sa_handler = SIG_DFL; + sigemptyset (&sa.sa_mask); + + for (i = 0; i < sizeof (handle_sigs) / sizeof (handle_sigs[0]); i++) + if (sigaction (handle_sigs[i], &sa, NULL) == -1) { + logger (LOG_ERR, "sigaction: %s", strerror (errno)); + return (-1); + } + + return (0); +} diff --git a/signal.h b/signal.h index eccec518..d7baa6e0 100644 --- a/signal.h +++ b/signal.h @@ -29,6 +29,7 @@ #define SIGNAL_H int signal_setup (void); +int signal_reset (void); int signal_fd_set (fd_set *rset, int fd); int signal_exists (const fd_set *rset); int signal_read (fd_set *rset);