DF-5766 / fix.diff
--- 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); + } } /* |