--- 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