git: 642701abc835 - main - kern: harvest entropy from callouts

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Thu, 03 Feb 2022 16:05:23 UTC
The branch main has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=642701abc8357d2e6512b324956cfbcd6f25b482

commit 642701abc8357d2e6512b324956cfbcd6f25b482
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2022-02-03 16:05:06 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2022-02-03 16:05:06 +0000

    kern: harvest entropy from callouts
    
    74cf7cae4d22 ("softclock: Use dedicated ithreads for running callouts.")
    switched callouts away from the swi infrastructure.  It turns out that
    this was a major source of entropy in early boot, which we've now lost.
    
    As a result, first boot on hardware without a 'fast' entropy source
    would block waiting for fortuna to be seeded with little hope of
    progressing without manual intervention.
    
    Let's resolve it by explicitly harvesting entropy in callout_process()
    if we've handled any callouts.  cc/curthread/now seem to be reasonable
    sources of entropy, so use those.
    
    Discussed with: jhb (also proposed initial patch)
    Reported by:    many
    Reviewed by:    cem, markm (both csprng)
    Differential Revision:  https://reviews.freebsd.org/D34150
---
 sys/dev/random/fenestrasX/fx_pool.c |  3 +++
 sys/dev/random/random_harvestq.c    |  3 ++-
 sys/kern/kern_timeout.c             | 11 +++++++++++
 sys/sys/random.h                    |  3 ++-
 4 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/sys/dev/random/fenestrasX/fx_pool.c b/sys/dev/random/fenestrasX/fx_pool.c
index b6cc0dad349d..f2fc15874b67 100644
--- a/sys/dev/random/fenestrasX/fx_pool.c
+++ b/sys/dev/random/fenestrasX/fx_pool.c
@@ -164,6 +164,9 @@ static const struct fxrng_ent_char {
 	[RANDOM_UMA] = {
 		.entc_cls = &fxrng_lo_push,
 	},
+	[RANDOM_CALLOUT] = {
+		.entc_cls = &fxrng_lo_push,
+	},
 	[RANDOM_PURE_OCTEON] = {
 		.entc_cls = &fxrng_hi_push,	/* Could be made pull. */
 	},
diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c
index 46c069126949..aae8ec9172d7 100644
--- a/sys/dev/random/random_harvestq.c
+++ b/sys/dev/random/random_harvestq.c
@@ -349,7 +349,8 @@ static const char *random_source_descr[ENTROPYSOURCE] = {
 	[RANDOM_INTERRUPT] = "INTERRUPT",
 	[RANDOM_SWI] = "SWI",
 	[RANDOM_FS_ATIME] = "FS_ATIME",
-	[RANDOM_UMA] = "UMA", /* ENVIRONMENTAL_END */
+	[RANDOM_UMA] = "UMA",
+	[RANDOM_CALLOUT] = "CALLOUT", /* ENVIRONMENTAL_END */
 	[RANDOM_PURE_OCTEON] = "PURE_OCTEON", /* PURE_START */
 	[RANDOM_PURE_SAFE] = "PURE_SAFE",
 	[RANDOM_PURE_GLXSB] = "PURE_GLXSB",
diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
index d0fb19661fa4..bc7b50e5ff8f 100644
--- a/sys/kern/kern_timeout.c
+++ b/sys/kern/kern_timeout.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
+#include <sys/random.h>
 #include <sys/sched.h>
 #include <sys/sdt.h>
 #include <sys/sleepqueue.h>
@@ -430,6 +431,11 @@ callout_get_bucket(sbintime_t sbt)
 void
 callout_process(sbintime_t now)
 {
+	struct callout_entropy {
+		struct callout_cpu *cc;
+		struct thread *td;
+		sbintime_t now;
+	} entropy;
 	struct callout *tmp, *tmpn;
 	struct callout_cpu *cc;
 	struct callout_list *sc;
@@ -545,6 +551,11 @@ next:
 	avg_lockcalls_dir += (lockcalls_dir * 1000 - avg_lockcalls_dir) >> 8;
 #endif
 	if (!TAILQ_EMPTY(&cc->cc_expireq)) {
+		entropy.cc = cc;
+		entropy.td = curthread;
+		entropy.now = now;
+		random_harvest_queue(&entropy, sizeof(entropy), RANDOM_CALLOUT);
+
 		td = cc->cc_thread;
 		if (TD_AWAITING_INTR(td)) {
 			thread_lock_block_wait(td);
diff --git a/sys/sys/random.h b/sys/sys/random.h
index cfcf4b30e698..6f4f90c9de98 100644
--- a/sys/sys/random.h
+++ b/sys/sys/random.h
@@ -86,7 +86,8 @@ enum random_entropy_source {
 	RANDOM_SWI,
 	RANDOM_FS_ATIME,
 	RANDOM_UMA,	/* Special!! UMA/SLAB Allocator */
-	RANDOM_ENVIRONMENTAL_END = RANDOM_UMA,
+	RANDOM_CALLOUT,
+	RANDOM_ENVIRONMENTAL_END = RANDOM_CALLOUT,
 	/* Fast hardware random-number sources from here on. */
 	RANDOM_PURE_START,
 	RANDOM_PURE_OCTEON = RANDOM_PURE_START,