X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/0f00dc4c8eb47e67bc0f148c2dd109f73a451e0a..61bd904b61ef893246791746517ef7a38ed732db:/rand/noise.c?ds=sidebyside diff --git a/rand/noise.c b/rand/noise.c index 6ab1070f..3bece706 100644 --- a/rand/noise.c +++ b/rand/noise.c @@ -30,9 +30,10 @@ #include "config.h" #include +#include #include +#include #include -#include #include #include @@ -46,6 +47,8 @@ #endif #include +#include +#include #include #include "noise.h" @@ -113,6 +116,7 @@ static int timer(rand_pool *r, struct timeval *tv) x = tv->tv_usec + MILLION * tv->tv_sec; d = x ^ noise_last; dd = d ^ noise_diff; + noise_last = x; noise_diff = d; de = bitcount(d); dde = bitcount(dd); @@ -156,6 +160,7 @@ int noise_devrandom(rand_pool *r) int fd; octet buf[RAND_POOLSZ]; ssize_t len; + size_t n = 0; int ret = 0; /* --- Be nice to other clients of the random device --- * @@ -169,11 +174,13 @@ int noise_devrandom(rand_pool *r) if ((fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK)) >= 0 || (fd = open("/dev/arandom", O_RDONLY | O_NONBLOCK)) >= 0 || (fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) >= 0) { - if ((len = read(fd, buf, sizeof(buf))) > 0) { - rand_add(r, buf, len, len * 8); - BURN(buf); - ret = 1; + while (n < sizeof(buf)) { + if ((len = read(fd, buf + n, sizeof(buf) - n)) <= 0) break; + n += len; } + rand_add(r, buf, n, n * 8); + BURN(buf); + if (n == sizeof(buf)) ret = 1; close(fd); } noise_timer(r); @@ -222,13 +229,43 @@ void noise_setid(uid_t uid, gid_t gid) * This interface is Unix-specific. */ +struct noisekid { + rand_pool *r; + int good; + char buf[4096]; + int donep; + int ret; +}; + +static void kid_read(int fd, unsigned mode, void *p) +{ + struct noisekid *nk = p; + ssize_t sz; + int goodbits; + + noise_timer(nk->r); + if ((sz = read(fd, nk->buf, sizeof(nk->buf))) <= 0) + nk->donep = 1; + else { + goodbits = (sz * nk->good) / 128; + rand_add(nk->r, nk->buf, sz, goodbits); + nk->ret = 1; + } +} + +static void kid_dead(struct timeval *tv, void *p) + { struct noisekid *nk = p; nk->donep = 1; } + int noise_filter(rand_pool *r, int good, const char *c) { - char buf[4096]; pid_t kid; int fd[2]; struct timeval dead; int ret = 0; + struct noisekid nk = { 0 }; + sel_state sel; + sel_file sf; + sel_timer st; const char *env[] = { "PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc", 0 @@ -257,20 +294,16 @@ int noise_filter(rand_pool *r, int good, const char *c) /* --- Handle the child end of the deal --- */ if (kid == 0) { - int f; + mdup_fd mfd[3]; + int f, i = 0; /* --- Set the pipe as standard output, close standard input --- */ - close(0); close(1); close(2); - - if (fd[1] != 1) { - if (dup2(fd[1], 1) < 0) _exit(127); - close(fd[1]); - } - - if ((f = open("/dev/null", O_RDONLY)) != 0 || - (f = open("/dev/null", O_WRONLY)) != 2) - _exit(127); + if ((f = open("/dev/null", O_RDONLY)) < 0) _exit(127); + mfd[i].cur = f; mfd[i].want = 0; i++; + mfd[i].cur = fd[1]; mfd[i].want = 1; i++; + mfd[i].cur = f; mfd[i].want = 2; i++; + if (mdup(mfd, i)) _exit(127); /* --- Play games with uids --- */ @@ -289,46 +322,20 @@ int noise_filter(rand_pool *r, int good, const char *c) /* --- Start the process up --- */ - execle("/bin/sh", "-c", c, (char *)0, env); + execle("/bin/sh", "sh", "-c", c, (char *)0, env); _exit(127); } /* --- Sort out my end of the deal --- */ close(fd[1]); - - /* --- Decide on the deadline --- */ - + sel_init(&sel); + nk.r = r; nk.good = good; TV_ADDL(&dead, &dead, 0, NOISE_KIDLIFE); - - /* --- Now read, and think --- */ - - for (;;) { - struct timeval now, diff; - fd_set rd; - - gettimeofday(&now, 0); - timer(r, &now); - if (TV_CMP(&now, >, &dead)) - break; - TV_SUB(&diff, &dead, &now); - - FD_ZERO(&rd); - FD_SET(fd[0], &rd); - - if (select(fd[0] + 1, &rd, 0, 0, &diff) < 0) - break; - if (FD_ISSET(fd[0], &rd)) { - ssize_t sz; - int goodbits; - - if ((sz = read(fd[0], buf, sizeof(buf))) <= 0) - break; - goodbits = (sz * good) / 128; - rand_add(r, buf, sz, goodbits); - ret = 1; - } - } + sel_initfile(&sel, &sf, fd[0], SEL_READ, kid_read, &nk); + sel_addfile(&sf); + sel_addtimer(&sel, &st, &dead, kid_dead, &nk); + while (!nk.donep && !sel_select(&sel)); /* --- We've finished with it: kill the child process --- * * @@ -338,11 +345,11 @@ int noise_filter(rand_pool *r, int good, const char *c) */ close(fd[0]); - BURN(buf); + BURN(nk.buf); noise_timer(r); kill(kid, SIGKILL); waitpid(kid, 0, 0); - return (ret); + return (nk.ret); } /* --- @noise_freewheel@ --- * @@ -449,7 +456,7 @@ void noise_acquire(rand_pool *r) unsigned i; for (i = 0; i < 8; i++) noise_freewheel(r); - if (!noise_devrandom(r)) { + if (!noise_devrandom(r) || getenv("CATACOMB_FORCE_ESOTERIC_SOURCES")) { noise_enquire(r); for (i = 0; i < 8; i++) noise_freewheel(r);