On many machines arch_get_random_long() gives 64 bits but current code uses only 32 of them since it XORs the result into p[14] which is u32. --- My previous patch made an unwarranted assumption that an array declared u32 would be 64-bit aligned. Thanks to Eric for catching that. This version avoids that problem and also handles the case where on some machines a long is only 32 bits. drivers/char/random.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 605969ed0f96..2c6b56cf8b27 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -989,14 +989,19 @@ static void _extract_crng(struct crng_state *crng, __u8 out[CHACHA_BLOCK_SIZE]) { unsigned long v, flags; + u32 *q ; + q = (u32 *) &v ; if (crng_ready() && (time_after(crng_global_init_time, crng->init_time) || time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))) crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL); spin_lock_irqsave(&crng->lock, flags); - if (arch_get_random_long(&v)) - crng->state[14] ^= v; + if (arch_get_random_long(&v)) { + p[14] ^= q[0] ; + if (sizeof(v) == 8) + p[15] ^= q[1] ; + } chacha20_block(&crng->state[0], out); if (crng->state[12] == 0) crng->state[13]++;