9012e9e
commit 62838c656e342608ab7aa4e58c567987e4342a55
9012e9e
Author: Jeff Garzik <jeff@garzik.org>
9012e9e
Date:   Tue Aug 17 15:59:01 2010 -0400
9012e9e
9012e9e
    Disable entropy source, if facing continued failures.
9012e9e
    
9012e9e
    If all entropy sources are disabled, exit.
9012e9e
    
9012e9e
    Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
9012e9e
9012e9e
diff --git a/rngd.c b/rngd.c
9012e9e
index 6ebef64..6a7f120 100644
9012e9e
--- a/rngd.c
9012e9e
+++ b/rngd.c
9012e9e
@@ -111,16 +111,12 @@ static struct rng rng_default = {
9012e9e
 	.rng_name	= "/dev/hw_random",
9012e9e
 	.rng_fd		= -1,
9012e9e
 	.xread		= xread,
9012e9e
-	.fipsctx	= NULL,
9012e9e
-	.next		= NULL,
9012e9e
 };
9012e9e
 
9012e9e
 static struct rng rng_tpm = {
9012e9e
 	.rng_name	= "/dev/tpm0",
9012e9e
 	.rng_fd		= -1,
9012e9e
 	.xread		= xread_tpm,
9012e9e
-	.fipsctx	= NULL,
9012e9e
-	.next		= NULL,
9012e9e
 };
9012e9e
 
9012e9e
 struct rng *rng_list;
9012e9e
@@ -207,18 +203,46 @@ static void do_loop(int random_step, double poll_timeout)
9012e9e
 {
9012e9e
 	unsigned char buf[FIPS_RNG_BUFFER_SIZE];
9012e9e
 	int retval;
9012e9e
+	int no_work = 0;
9012e9e
 
9012e9e
-	for (;;) {
9012e9e
+	while (no_work < 100) {
9012e9e
 		struct rng *iter;
9012e9e
+		bool work_done;
9012e9e
+
9012e9e
+		work_done = false;
9012e9e
 		for (iter = rng_list; iter; iter = iter->next)
9012e9e
 		{
9012e9e
+			int rc;
9012e9e
+
9012e9e
+			if (iter->disabled)
9012e9e
+				continue;	/* failed, no work */
9012e9e
+
9012e9e
 			retval = iter->xread(buf, sizeof buf, iter);
9012e9e
-			if (retval == 0)
9012e9e
-				update_kernel_random(random_step,
9012e9e
-						     poll_timeout, buf,
9012e9e
-						     iter->fipsctx);
9012e9e
+			if (retval)
9012e9e
+				continue;	/* failed, no work */
9012e9e
+
9012e9e
+			work_done = true;
9012e9e
+
9012e9e
+			rc = update_kernel_random(random_step,
9012e9e
+					     poll_timeout, buf,
9012e9e
+					     iter->fipsctx);
9012e9e
+			if (rc == 0)
9012e9e
+				continue;	/* succeeded, work done */
9012e9e
+
9012e9e
+			iter->failures++;
9012e9e
+			if (iter->failures == MAX_RNG_FAILURES) {
9012e9e
+				message(LOG_DAEMON|LOG_ERR,
9012e9e
+					"too many FIPS failures, disabling entropy source\n");
9012e9e
+				iter->disabled = true;
9012e9e
+			}
9012e9e
 		}
9012e9e
+
9012e9e
+		if (!work_done)
9012e9e
+			no_work++;
9012e9e
 	}
9012e9e
+
9012e9e
+	message(LOG_DAEMON|LOG_ERR,
9012e9e
+		"No entropy sources working, exiting rngd\n");
9012e9e
 }
9012e9e
 
9012e9e
 int main(int argc, char **argv)
9012e9e
diff --git a/rngd.h b/rngd.h
9012e9e
index 6e7e83f..bcc6f59 100644
9012e9e
--- a/rngd.h
9012e9e
+++ b/rngd.h
9012e9e
@@ -27,11 +27,16 @@
9012e9e
 
9012e9e
 #include <unistd.h>
9012e9e
 #include <stdint.h>
9012e9e
+#include <stdbool.h>
9012e9e
 #include <stdio.h>
9012e9e
 #include <syslog.h>
9012e9e
 
9012e9e
 #include "fips.h"
9012e9e
 
9012e9e
+enum {
9012e9e
+	MAX_RNG_FAILURES		= 25,
9012e9e
+};
9012e9e
+
9012e9e
 /* Command line arguments and processing */
9012e9e
 struct arguments {
9012e9e
 	char *random_name;
9012e9e
@@ -49,6 +54,8 @@ extern struct arguments *arguments;
9012e9e
 struct rng {
9012e9e
 	char *rng_name;
9012e9e
 	int rng_fd;
9012e9e
+	bool disabled;
9012e9e
+	int failures;
9012e9e
 
9012e9e
 	int (*xread) (void *buf, size_t size, struct rng *ent_src);
9012e9e
 	fips_ctx_t *fipsctx;