Skip to content

Commit 73c7733

Browse files
committed
random: do not throw away excess input to crng_fast_load
When crng_fast_load() is called by add_hwgenerator_randomness(), we currently will advance to crng_init==1 once we've acquired 64 bytes, and then throw away the rest of the buffer. Usually, that is not a problem: When add_hwgenerator_randomness() gets called via EFI or DT during setup_arch(), there won't be any IRQ randomness. Therefore, the 64 bytes passed by EFI exactly matches what is needed to advance to crng_init==1. Usually, DT seems to pass 64 bytes as well -- with one notable exception being kexec, which hands over 128 bytes of entropy to the kexec'd kernel. In that case, we'll advance to crng_init==1 once 64 of those bytes are consumed by crng_fast_load(), but won't continue onward feeding in bytes to progress to crng_init==2. This commit fixes the issue by feeding any leftover bytes into the next phase in add_hwgenerator_randomness(). [[email protected]: rewrite commit message] Signed-off-by: Dominik Brodowski <[email protected]> Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent 9c3ddde commit 73c7733

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

drivers/char/random.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -919,12 +919,14 @@ static struct crng_state *select_crng(void)
919919

920920
/*
921921
* crng_fast_load() can be called by code in the interrupt service
922-
* path. So we can't afford to dilly-dally.
922+
* path. So we can't afford to dilly-dally. Returns the number of
923+
* bytes processed from cp.
923924
*/
924-
static int crng_fast_load(const char *cp, size_t len)
925+
static size_t crng_fast_load(const char *cp, size_t len)
925926
{
926927
unsigned long flags;
927928
char *p;
929+
size_t ret = 0;
928930

929931
if (!spin_trylock_irqsave(&primary_crng.lock, flags))
930932
return 0;
@@ -935,15 +937,15 @@ static int crng_fast_load(const char *cp, size_t len)
935937
p = (unsigned char *) &primary_crng.state[4];
936938
while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) {
937939
p[crng_init_cnt % CHACHA_KEY_SIZE] ^= *cp;
938-
cp++; crng_init_cnt++; len--;
940+
cp++; crng_init_cnt++; len--; ret++;
939941
}
940942
spin_unlock_irqrestore(&primary_crng.lock, flags);
941943
if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
942944
invalidate_batched_entropy();
943945
crng_init = 1;
944946
pr_notice("fast init done\n");
945947
}
946-
return 1;
948+
return ret;
947949
}
948950

949951
/*
@@ -1294,7 +1296,7 @@ void add_interrupt_randomness(int irq)
12941296
if (unlikely(crng_init == 0)) {
12951297
if ((fast_pool->count >= 64) &&
12961298
crng_fast_load((char *) fast_pool->pool,
1297-
sizeof(fast_pool->pool))) {
1299+
sizeof(fast_pool->pool)) > 0) {
12981300
fast_pool->count = 0;
12991301
fast_pool->last = now;
13001302
}
@@ -2295,8 +2297,11 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
22952297
struct entropy_store *poolp = &input_pool;
22962298

22972299
if (unlikely(crng_init == 0)) {
2298-
crng_fast_load(buffer, count);
2299-
return;
2300+
size_t ret = crng_fast_load(buffer, count);
2301+
count -= ret;
2302+
buffer += ret;
2303+
if (!count || crng_init == 0)
2304+
return;
23002305
}
23012306

23022307
/* Suspend writing if we're above the trickle threshold.

0 commit comments

Comments
 (0)