`Currently, we do the jitter dance if two consecutive reads to the cyclecounter return different values. If they do, then we consider the cyclecounter to be fast enough that one trip through the scheduler will yieldone "bit" of credited entropy. If those two reads return the same value,then we assume the cycle counter is too slow to show meaningfuldifferences.This methodology is flawed for a variety of reasons, one of which Ericposted a patch to fix in [1]. The issue that patch solves is that on asystem with a slow counter, you might be [un]lucky and read the counter_just_ before it changes, so that the second cycle counter you readdiffers from the first, even though there's usually quite a large periodof time in between the two. For example:| real time | cycle counter || --------- | ------------- || 3         | 5             || 4         | 5             || 5         | 5             || 6         | 5             || 7         | 5             | <--- a| 8         | 6             | <--- b| 9         | 6             | <--- cIf we read the counter at (a) and compare it to (b), we might be fooledinto thinking that it's a fast counter, when in reality it is not. Thesolution in [1] is to also compare counter (b) to counter (c), on thetheory that if the counter is _actually_ slow, and (a)!=(b), thencertainly (b)==(c).This helps solve this particular issue, in one sense, but in anothersense, it mostly functions to disallow jitter entropy on these systems,rather than simply taking more samples in that case.Instead, this patch takes a different approach. Right now we assume thata difference in one set of consecutive samples means one "bit" ofcredited entropy per scheduler trip. We can extend this so that adifference in two sets of consecutive samples means one "bit" ofcredited entropy per /two/ scheduler trips, and three for three, andfour for four. In other words, we can increase the amount of jitter"work" we require for each "bit", depending on how slow the cyclecounter is.So this patch takes whole bunch of samples, sees how many of them aredifferent, and divides to find the amount of work required per "bit",and also requires that at least some minimum of them are different inorder to attempt any jitter entropy.Note that this approach is still far from perfect. It's not a realstatistical estimate on how much these samples vary; it's not areal-time analysis of the relevant input data. That remains a projectfor another time. However, it does the same (partly flawed) assumptionsas the code that's there now, so it's probably not worse than the statusquo, and it handles the issue Eric mentioned in [1]. But, again, it'sprobably a far cry from whatever a really robust version of this wouldbe.[1] https://lore.kernel.org/lkml/20220421233152.58522-1-ebiggers@kernel.org/    https://lore.kernel.org/lkml/20220421192939.250680-1-ebiggers@kernel.org/Cc: Eric Biggers <ebiggers@google.com>Cc: Theodore Ts'o <tytso@mit.edu>Cc: Linus Torvalds <torvalds@linux-foundation.org>Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>---This is an argument very much centered around the somewhat low bar ofbeing "not worse than before". If you can think of ways that it doesn'teven manage to clear that, please do pipe up. drivers/char/random.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-)diff --git a/drivers/char/random.c b/drivers/char/random.cindex bf89c6f27a19..94a2ddb53662 100644--- a/drivers/char/random.c+++ b/drivers/char/random.c@@ -1354,6 +1354,12 @@ void add_interrupt_randomness(int irq) } EXPORT_SYMBOL_GPL(add_interrupt_randomness); +struct entropy_timer_state {+	unsigned long entropy;+	struct timer_list timer;+	unsigned int samples, samples_per_bit;+};+ /*  * Each time the timer fires, we expect that we got an unpredictable  * jump in the cycle counter. Even if the timer is running on another@@ -1367,9 +1373,14 @@ EXPORT_SYMBOL_GPL(add_interrupt_randomness);  *  * So the re-arming always happens in the entropy loop itself.  */-static void entropy_timer(struct timer_list *t)+static void entropy_timer(struct timer_list *timer) {-	credit_entropy_bits(1);+	struct entropy_timer_state *state = container_of(timer, struct entropy_timer_state, timer);++	if (++state->samples == state->samples_per_bit) {+		credit_entropy_bits(1);+		state->samples = 0;+	} }  /*@@ -1378,17 +1389,22 @@ static void entropy_timer(struct timer_list *t)  */ static void try_to_generate_entropy(void) {-	struct {-		unsigned long entropy;-		struct timer_list timer;-	} stack;--	stack.entropy = random_get_entropy();+	enum { NUM_TRIAL_SAMPLES = 8192, MAX_SAMPLES_PER_BIT = 256 };+	struct entropy_timer_state stack;+	unsigned int i, num_different = 0;+	unsigned long last = random_get_entropy(); -	/* Slow counter - or none. Don't even bother */-	if (stack.entropy == random_get_entropy())+	for (i = 0; i < NUM_TRIAL_SAMPLES - 1; ++i) {+		stack.entropy = random_get_entropy();+		if (stack.entropy != last)+			++num_different;+		last = stack.entropy;+	}+	stack.samples_per_bit = DIV_ROUND_UP(NUM_TRIAL_SAMPLES, num_different + 1);+	if (stack.samples_per_bit > MAX_SAMPLES_PER_BIT) 		return; +	stack.samples = 0; 	timer_setup_on_stack(&stack.timer, entropy_timer, 0); 	while (!crng_ready() && !signal_pending(current)) { 		if (!timer_pending(&stack.timer))-- 2.35.1`