---
 src/dnsmasq.c |  6 +++---
 src/dnsmasq.h |  1 +
 src/helper.c  |  4 ++--
 src/util.c    | 21 +++++++++++++++++++++
 4 files changed, 27 insertions(+), 5 deletions(-)

diff --git src/dnsmasq.c src/dnsmasq.c
index a9f26ae3..d15177f8 100644
--- src/dnsmasq.c
+++ src/dnsmasq.c
@@ -607,7 +607,7 @@ int main (int argc, char **argv)
             When startup is complete we close this and the process terminates. 
*/
          safe_pipe(err_pipe, 0);
          
-         if ((pid = fork()) == -1)
+         if ((pid = my_fork()) == -1)
            /* fd == -1 since we've not forked, never returns. */
            send_event(-1, EVENT_FORK_ERR, errno, NULL);
           
@@ -632,7 +632,7 @@ int main (int argc, char **argv)
          
          setsid();
         
-         if ((pid = fork()) == -1)
+         if ((pid = my_fork()) == -1)
            send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
         
          if (pid != 0)
@@ -1955,7 +1955,7 @@ static void check_dns_listeners(time_t now)
              shutdown(confd, SHUT_RDWR);
              close(confd);
            }
-         else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) 
!= 0)
+         else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = 
my_fork()) != 0)
            {
              close(pipefd[1]); /* parent needs read pipe end. */
              if (p == -1)
diff --git src/dnsmasq.h src/dnsmasq.h
index e455c3f7..ff926bf8 100644
--- src/dnsmasq.h
+++ src/dnsmasq.h
@@ -1462,6 +1462,7 @@ unsigned char *do_rfc1035_name(unsigned char *p, char 
*sval, char *limit);
 void *safe_malloc(size_t size);
 void safe_strncpy(char *dest, const char *src, size_t size);
 void safe_pipe(int *fd, int read_noblock);
+pid_t my_fork(void);
 void *whine_malloc(size_t size);
 void *whine_realloc(void *ptr, size_t size);
 int sa_len(union mysockaddr *addr);
diff --git src/helper.c src/helper.c
index b9da2259..a5714303 100644
--- src/helper.c
+++ src/helper.c
@@ -85,7 +85,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t 
gid, long max_fd)
   
   /* create the pipe through which the main program sends us commands,
      then fork our process. */
-  if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1)
+  if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = my_fork()) == -1)
     {
       send_event(err_fd, EVENT_PIPE_ERR, errno, NULL);
       _exit(0);
@@ -506,7 +506,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, 
gid_t gid, long max_fd)
        continue;
       
       /* possible fork errors are all temporary resource problems */
-      while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))
+      while ((pid = my_fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))
        sleep(2);
 
       if (pid == -1)
diff --git src/util.c src/util.c
index 71b1dd57..28b9c6d2 100644
--- src/util.c
+++ src/util.c
@@ -64,6 +64,18 @@ void rand_init()
     die(_("failed to seed the random number generator: %s"), NULL, EC_MISC);
 }
 
+static void rand_atfork(pid_t fpid)
+{
+  u32 next[countof(seed)];
+  for (unsigned int i = 0; i < countof(seed); i++)
+    next[i] = rand32();
+  // Child reseeds the state with generated values.  Parent skips those values 
explicitly as they
+  // might be exposed to an external observer and used to guess something 
about PRNG of the child.
+  if (fpid == 0)
+    for (unsigned int i = 0; i < countof(seed); i++)
+      seed[i] ^= next[i];
+}
+
 #define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b))))
 #define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b));
 
@@ -334,6 +346,15 @@ void safe_pipe(int *fd, int read_noblock)
     die(_("cannot create pipe: %s"), NULL, EC_MISC);
 }
 
+// pthread_atfork() might be a better way to wrap fork(), but it requires 
-pthread besides libc.
+pid_t my_fork()
+{
+  const pid_t fpid = fork();
+  if (fpid != -1)
+    rand_atfork(fpid);
+  return fpid;
+}
+
 void *whine_malloc(size_t size)
 {
   void *ret = calloc(1, size);
-- 
2.34.1


_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss

Reply via email to