git: 97792a587051 - stable/15 - random: Make the entropy source registration interface more uniform

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Tue, 30 Sep 2025 15:23:42 UTC
The branch stable/15 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=97792a587051fd3cebf7ed30879c6e552ff5c13f

commit 97792a587051fd3cebf7ed30879c6e552ff5c13f
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-09-08 14:41:47 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-09-30 09:43:08 +0000

    random: Make the entropy source registration interface more uniform
    
    Most pure sources work under a "pull" model wherein a dedicated thread
    polls the source at regular intervals (every 100ms).  A couple of
    sources, however, will instead call random_harvest_direct() to provide
    entropy samples.  Such sources were not calling random_source_register()
    and thus weren't in the global random source list.
    
    Modify "push" sources to use random_source_register() like other sources
    do.  Such sources omit an implementation of rs_read and are thus skipped
    by the above-mentioned thread.  This makes it easier to allow pure
    sources to provide a min-entropy estimate in a uniform way.
    
    Reviewed by:    cem
    MFC after:      2 weeks
    Sponsored by:   Stormshield
    Sponsored by:   Klara, Inc.
    Differential Revision:  https://reviews.freebsd.org/D52229
    
    (cherry picked from commit 8635f86977638eed966ec59cd319521fffb4df70)
---
 sys/dev/random/random_harvestq.c | 29 ++++++++++-------------------
 sys/dev/random/randomdev.h       |  2 ++
 sys/dev/tpm/tpm20.c              | 13 ++++++++++---
 sys/dev/vmgenc/vmgenc_acpi.c     |  8 +++++++-
 sys/sys/random.h                 |  3 ---
 5 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c
index 20727471f9c7..eb3808d692bb 100644
--- a/sys/dev/random/random_harvestq.c
+++ b/sys/dev/random/random_harvestq.c
@@ -278,8 +278,15 @@ random_sources_feed(void)
 		epoch_enter_preempt(rs_epoch, &et);
 	CK_LIST_FOREACH(rrs, &source_list, rrs_entries) {
 		for (i = 0; i < npools; i++) {
+			if (rrs->rrs_source->rs_read == NULL) {
+				/* Source pushes entropy asynchronously. */
+				continue;
+			}
 			n = rrs->rrs_source->rs_read(entropy, sizeof(entropy));
-			KASSERT((n <= sizeof(entropy)), ("%s: rs_read returned too much data (%u > %zu)", __func__, n, sizeof(entropy)));
+			KASSERT((n <= sizeof(entropy)),
+			    ("%s: rs_read returned too much data (%u > %zu)",
+			    __func__, n, sizeof(entropy)));
+
 			/*
 			 * Sometimes the HW entropy source doesn't have anything
 			 * ready for us.  This isn't necessarily untrustworthy.
@@ -866,20 +873,6 @@ random_harvest_direct_(const void *entropy, u_int size, enum random_entropy_sour
 	random_harvestq_fast_process_event(&event);
 }
 
-void
-random_harvest_register_source(enum random_entropy_source source)
-{
-
-	hc_source_mask |= (1 << source);
-}
-
-void
-random_harvest_deregister_source(enum random_entropy_source source)
-{
-
-	hc_source_mask &= ~(1 << source);
-}
-
 void
 random_source_register(const struct random_source *rsource)
 {
@@ -890,10 +883,9 @@ random_source_register(const struct random_source *rsource)
 	rrs = malloc(sizeof(*rrs), M_ENTROPY, M_WAITOK);
 	rrs->rrs_source = rsource;
 
-	random_harvest_register_source(rsource->rs_source);
-
 	printf("random: registering fast source %s\n", rsource->rs_ident);
 
+	hc_source_mask |= (1 << rsource->rs_source);
 	RANDOM_HARVEST_LOCK();
 	CK_LIST_INSERT_HEAD(&source_list, rrs, rrs_entries);
 	RANDOM_HARVEST_UNLOCK();
@@ -906,8 +898,7 @@ random_source_deregister(const struct random_source *rsource)
 
 	KASSERT(rsource != NULL, ("invalid input to %s", __func__));
 
-	random_harvest_deregister_source(rsource->rs_source);
-
+	hc_source_mask &= ~(1 << rsource->rs_source);
 	RANDOM_HARVEST_LOCK();
 	CK_LIST_FOREACH(rrs, &source_list, rrs_entries)
 		if (rrs->rrs_source == rsource) {
diff --git a/sys/dev/random/randomdev.h b/sys/dev/random/randomdev.h
index 6d742447ea8b..0fa92f8c9575 100644
--- a/sys/dev/random/randomdev.h
+++ b/sys/dev/random/randomdev.h
@@ -52,7 +52,9 @@ random_check_uint_##name(SYSCTL_HANDLER_ARGS)				\
 }
 #endif /* SYSCTL_DECL */
 
+#ifdef MALLOC_DECLARE
 MALLOC_DECLARE(M_ENTROPY);
+#endif
 
 extern bool random_bypass_before_seeding;
 extern bool read_random_bypassed_before_seeding;
diff --git a/sys/dev/tpm/tpm20.c b/sys/dev/tpm/tpm20.c
index 876dd0bcc40d..067e7ccae8f9 100644
--- a/sys/dev/tpm/tpm20.c
+++ b/sys/dev/tpm/tpm20.c
@@ -25,8 +25,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/cdefs.h>
 #include <sys/random.h>
+#include <dev/random/randomdev.h>
 
 #include "tpm20.h"
 
@@ -184,6 +184,13 @@ tpm20_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
 	return (ENOTTY);
 }
 
+#ifdef TPM_HARVEST
+static const struct random_source random_tpm = {
+	.rs_ident = "TPM",
+	.rs_source = RANDOM_PURE_TPM,
+};
+#endif
+
 int
 tpm20_init(struct tpm_sc *sc)
 {
@@ -206,7 +213,7 @@ tpm20_init(struct tpm_sc *sc)
 		tpm20_release(sc);
 
 #ifdef TPM_HARVEST
-	random_harvest_register_source(RANDOM_PURE_TPM);
+	random_source_register(&random_tpm);
 	TIMEOUT_TASK_INIT(taskqueue_thread, &sc->harvest_task, 0,
 	    tpm20_harvest, sc);
 	taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task, 0);
@@ -223,7 +230,7 @@ tpm20_release(struct tpm_sc *sc)
 #ifdef TPM_HARVEST
 	if (device_is_attached(sc->dev))
 		taskqueue_drain_timeout(taskqueue_thread, &sc->harvest_task);
-	random_harvest_deregister_source(RANDOM_PURE_TPM);
+	random_source_deregister(&random_tpm);
 #endif
 
 	if (sc->buf != NULL)
diff --git a/sys/dev/vmgenc/vmgenc_acpi.c b/sys/dev/vmgenc/vmgenc_acpi.c
index 2ad8929dfd34..18519a8e4f22 100644
--- a/sys/dev/vmgenc/vmgenc_acpi.c
+++ b/sys/dev/vmgenc/vmgenc_acpi.c
@@ -56,6 +56,7 @@
 #include <contrib/dev/acpica/include/acpi.h>
 
 #include <dev/acpica/acpivar.h>
+#include <dev/random/randomdev.h>
 #include <dev/random/random_harvestq.h>
 #include <dev/vmgenc/vmgenc_acpi.h>
 
@@ -210,6 +211,11 @@ acpi_GetPackedUINT64(device_t dev, ACPI_HANDLE handle, char *path,
 
 }
 
+static const struct random_source random_vmgenid = {
+	.rs_ident = "VM Generation ID",
+	.rs_source = RANDOM_PURE_VMGENID,
+};
+
 static int
 vmgenc_attach(device_t dev)
 {
@@ -234,7 +240,7 @@ vmgenc_attach(device_t dev)
 	memcpy(sc->vmg_cache_guid, __DEVOLATILE(void *, sc->vmg_pguid),
 	    sizeof(sc->vmg_cache_guid));
 
-	random_harvest_register_source(RANDOM_PURE_VMGENID);
+	random_source_register(&random_vmgenid);
 	vmgenc_harvest_all(sc->vmg_cache_guid, sizeof(sc->vmg_cache_guid));
 
 	AcpiInstallNotifyHandler(h, ACPI_DEVICE_NOTIFY, vmgenc_notify, dev);
diff --git a/sys/sys/random.h b/sys/sys/random.h
index 5abf762cd200..2a68f0c99b6d 100644
--- a/sys/sys/random.h
+++ b/sys/sys/random.h
@@ -142,9 +142,6 @@ random_harvest_direct(const void *entropy, u_int size, enum random_entropy_sourc
 		random_harvest_direct_(entropy, size, origin);
 }
 
-void random_harvest_register_source(enum random_entropy_source);
-void random_harvest_deregister_source(enum random_entropy_source);
-
 #if defined(RANDOM_ENABLE_UMA)
 #define random_harvest_fast_uma(a, b, c)	random_harvest_fast(a, b, c)
 #else /* !defined(RANDOM_ENABLE_UMA) */