Commit | Line | Data |
---|---|---|
dd698971 MB |
1 | Try to actively add entropy instead of waiting forever. |
2 | Fixes <https://bugs.gnu.org/37501>. | |
3 | ||
4 | Taken from upstream: | |
5 | https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/patch/?id=50ee7529ec4500c88f8664560770a7a1b65db72b | |
6 | ||
7 | diff --git a/drivers/char/random.c b/drivers/char/random.c | |
8 | index 5d5ea4ce1442..2fda6166c1dd 100644 | |
9 | --- a/drivers/char/random.c | |
10 | +++ b/drivers/char/random.c | |
11 | @@ -1731,6 +1731,56 @@ void get_random_bytes(void *buf, int nbytes) | |
12 | } | |
13 | EXPORT_SYMBOL(get_random_bytes); | |
14 | ||
15 | + | |
16 | +/* | |
17 | + * Each time the timer fires, we expect that we got an unpredictable | |
18 | + * jump in the cycle counter. Even if the timer is running on another | |
19 | + * CPU, the timer activity will be touching the stack of the CPU that is | |
20 | + * generating entropy.. | |
21 | + * | |
22 | + * Note that we don't re-arm the timer in the timer itself - we are | |
23 | + * happy to be scheduled away, since that just makes the load more | |
24 | + * complex, but we do not want the timer to keep ticking unless the | |
25 | + * entropy loop is running. | |
26 | + * | |
27 | + * So the re-arming always happens in the entropy loop itself. | |
28 | + */ | |
29 | +static void entropy_timer(struct timer_list *t) | |
30 | +{ | |
31 | + credit_entropy_bits(&input_pool, 1); | |
32 | +} | |
33 | + | |
34 | +/* | |
35 | + * If we have an actual cycle counter, see if we can | |
36 | + * generate enough entropy with timing noise | |
37 | + */ | |
38 | +static void try_to_generate_entropy(void) | |
39 | +{ | |
40 | + struct { | |
41 | + unsigned long now; | |
42 | + struct timer_list timer; | |
43 | + } stack; | |
44 | + | |
45 | + stack.now = random_get_entropy(); | |
46 | + | |
47 | + /* Slow counter - or none. Don't even bother */ | |
48 | + if (stack.now == random_get_entropy()) | |
49 | + return; | |
50 | + | |
51 | + timer_setup_on_stack(&stack.timer, entropy_timer, 0); | |
52 | + while (!crng_ready()) { | |
53 | + if (!timer_pending(&stack.timer)) | |
54 | + mod_timer(&stack.timer, jiffies+1); | |
55 | + mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now)); | |
56 | + schedule(); | |
57 | + stack.now = random_get_entropy(); | |
58 | + } | |
59 | + | |
60 | + del_timer_sync(&stack.timer); | |
61 | + destroy_timer_on_stack(&stack.timer); | |
62 | + mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now)); | |
63 | +} | |
64 | + | |
65 | /* | |
66 | * Wait for the urandom pool to be seeded and thus guaranteed to supply | |
67 | * cryptographically secure random numbers. This applies to: the /dev/urandom | |
68 | @@ -1745,7 +1795,17 @@ int wait_for_random_bytes(void) | |
69 | { | |
70 | if (likely(crng_ready())) | |
71 | return 0; | |
72 | - return wait_event_interruptible(crng_init_wait, crng_ready()); | |
73 | + | |
74 | + do { | |
75 | + int ret; | |
76 | + ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ); | |
77 | + if (ret) | |
78 | + return ret > 0 ? 0 : ret; | |
79 | + | |
80 | + try_to_generate_entropy(); | |
81 | + } while (!crng_ready()); | |
82 | + | |
83 | + return 0; | |
84 | } | |
85 | EXPORT_SYMBOL(wait_for_random_bytes); | |
86 |