changeset 5265:b3b3fad25788 draft

privsep: Init the arc4random seed before chrooting /dev/urandom isn't available in the chroot. So keep a fd open to it.
author Roy Marples <roy@marples.name>
date Sun, 24 May 2020 12:23:20 +0000
parents 868ac20cdbad
children 9ea5c678d8a6
files compat/arc4random.c src/privsep.c
diffstat 2 files changed, 27 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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");