# HG changeset patch # User Roy Marples # Date 1590323000 0 # Node ID b3b3fad257881cb5fa67bb6b6c850d470d8b8acc # Parent 868ac20cdbad40504d822f59e4632e6b8e4a2356 privsep: Init the arc4random seed before chrooting /dev/urandom isn't available in the chroot. So keep a fd open to it. diff -r 868ac20cdbad -r b3b3fad25788 compat/arc4random.c --- a/compat/arc4random.c Sun May 24 12:02:15 2020 +0000 +++ b/compat/arc4random.c Sun May 24 12:23:20 2020 +0000 @@ -37,6 +37,7 @@ uint8_t s[256]; size_t count; pid_t stir_pid; + int fd; }; #define S(n) (n) @@ -46,7 +47,7 @@ #define S256 S64(0), S64(64), S64(128), S64(192) static struct arc4_stream rs = { .i = 0xff, .j = 0, .s = { S256 }, - .count = 0, .stir_pid = 0 }; + .count = 0, .stir_pid = 0, .fd = -1 }; #undef S #undef S4 @@ -103,7 +104,6 @@ static void arc4_stir(struct arc4_stream *as) { - int fd; struct { struct timeval tv; unsigned int rnd[(128 - sizeof(struct timeval)) / @@ -112,13 +112,28 @@ size_t n; gettimeofday(&rdat.tv, NULL); - fd = open("/dev/urandom", O_RDONLY); - if (fd != -1) { + if (as->fd == -1) { +#ifndef O_CLOEXEC + int fd_opts; +#endif + + as->fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK +#ifdef O_CLOEXEC + | O_CLOEXEC +#endif + ); +#ifndef O_CLOEXEC + if (as->fd != -1 && + (fd_opts = fcntl(as->fd, F_GETFD))) + fcntl(as->fd, F_SETFD, fd_opts | FD_CLOEXEC); +#endif + } + + if (as->fd != -1) { /* If there is an error reading, just use what is * on the stack. */ /* coverity[check_return] */ - (void)read(fd, rdat.rnd, sizeof(rdat.rnd)); - close(fd); + (void)read(as->fd, rdat.rnd, sizeof(rdat.rnd)); } /* fd < 0? Ah, what the heck. We'll just take diff -r 868ac20cdbad -r b3b3fad25788 src/privsep.c --- a/src/privsep.c Sun May 24 12:02:15 2020 +0000 +++ b/src/privsep.c Sun May 24 12:23:20 2020 +0000 @@ -321,6 +321,12 @@ TAILQ_INIT(&ctx->ps_processes); +#ifdef ARC4RANDOM_H + /* Seed the random number generator early incase it needs /dev/urandom + * which won't be available in the chroot. */ + arc4random(); +#endif + switch (pid = ps_root_start(ctx)) { case -1: logerr("ps_root_start");