Index: sys/dev/random/randomdev.c =================================================================== --- sys/dev/random/randomdev.c +++ sys/dev/random/randomdev.c @@ -257,6 +257,12 @@ if (len == 0) return; +#ifdef INVARIANTS + if ((curthread->td_pflags & TDP_RNG_SEEDED) == 0) + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, + "read_random may block once"); +#endif + /* (Un)Blocking logic */ if (__predict_false(!p_random_alg_context->ra_seeded())) { if (random_bypass_before_seeding) { @@ -300,7 +306,18 @@ bool IS_RANDOM_SEEDED(void) { - return (p_random_alg_context->ra_seeded()); + bool seeded; + + seeded = p_random_alg_context->ra_seeded(); +#ifdef INVARIANTS + /* + * Mute false-positive WITNESS_WARNs for threads that have already + * confirmed seeded status. + */ + if (seeded) + curthread->td_pflags |= TDP_RNG_SEEDED; +#endif + return (seeded); } static __inline void Index: sys/libkern/arc4random.c =================================================================== --- sys/libkern/arc4random.c +++ sys/libkern/arc4random.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -177,6 +178,12 @@ u_int length; u_int8_t *p; +#ifdef INVARIANTS + if ((curthread->td_pflags & TDP_RNG_SEEDED) == 0) + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, + "arc4rand may block once"); +#endif + if (reseed || atomic_cmpset_int(&arc4rand_iniseed_state, ARC4_ENTR_HAVE, ARC4_ENTR_SEED)) CHACHA20_FOREACH(chacha20) chacha20_randomstir(chacha20); Index: sys/sys/proc.h =================================================================== --- sys/sys/proc.h +++ sys/sys/proc.h @@ -492,6 +492,7 @@ #define TDP_UIOHELD 0x10000000 /* Current uio has pages held in td_ma */ #define TDP_FORKING 0x20000000 /* Thread is being created through fork() */ #define TDP_EXECVMSPC 0x40000000 /* Execve destroyed old vmspace */ +#define TDP_RNG_SEEDED 0x80000000 /* This thread verified random seeded */ /* * Reasons that the current thread can not be run yet.