⬢ DragonFlyBSD Kernel Audit
DF-5766 / fix.diff
← back to finding ↓ download raw
--- a/sys/kern/subr_csprng.c
+++ b/sys/kern/subr_csprng.c
@@ -129,11 +129,33 @@
 {
 	int cnt;
 	int total_bytes = 0;
+	struct timeval now;
 
 again:
-	if (!state->callout_based_reseed &&
-	     ratecheck(&state->last_reseed, &csprng_reseed_interval)) {
-		csprng_reseed(state);
+	if (!state->callout_based_reseed) {
+		/*
+		 * getmicrouptime() can return an astronomically large
+		 * "uptime" very early in boot (before the cputimer is
+		 * fully coherent the delta in getmicrouptime underflows).
+		 * ratecheck() stores that value into last_reseed on its
+		 * first successful call, after which every later delta
+		 * is negative and reseeding is permanently disabled on
+		 * this state (observed live: the BSP state never reseeds
+		 * again for the whole uptime despite an eligible pool[0]).
+		 *
+		 * Treat a backwards timestamp as "interval elapsed" and
+		 * re-baseline, so a garbage baseline self-heals on the
+		 * first sane call.  Uptime is otherwise monotonic.
+		 */
+		getmicrouptime(&now);
+		if (state->last_reseed.tv_sec > now.tv_sec) {
+			bzero(&state->last_reseed,
+			      sizeof(state->last_reseed));
+		}
+		if (ratecheck(&state->last_reseed,
+			      &csprng_reseed_interval)) {
+			csprng_reseed(state);
+		}
 	}
 
 	/*