]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Block signals to avoid potential signal racing on BSD using fork.
authorRoy Marples <roy@marples.name>
Sat, 2 Feb 2008 19:17:08 +0000 (19:17 +0000)
committerRoy Marples <roy@marples.name>
Sat, 2 Feb 2008 19:17:08 +0000 (19:17 +0000)
configure.c
signal.c
signal.h

index 71282bb7a04e21388079ad7a59b7ff599a04117f..6372ee5519fc5a51fcb7cddfb5e29f0ca3d6ef6e 100644 (file)
 #include <unistd.h>
 
 #ifndef BSD
-#define HAVE_POSIX_SPAWN
+# define HAVE_POSIX_SPAWN
 #endif
 
 #ifdef HAVE_POSIX_SPAWN
-#include <spawn.h>
+# include <spawn.h>
+extern char **environ;
+#else
+# include <signal.h>
 #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);
index a61cb2349227d5e6a4bfe36334bf69533783ac56..d38efb474a8d80d23b817ac7428ed429addb0c50 100644 (file)
--- 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);
+}
index eccec5181cf99a32299b26344dfdd5568e6b0beb..d7baa6e027305f66333a7c1bd170b65daa8fb903 100644 (file)
--- 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);