On Tue, Apr 02, 2019 at 06:00:25PM -0400, Neil Horman wrote: > When _crng_extract is called, any arch that has a registered > arch_get_random_long method, attempts to mix an unsigned long value into > the crng->state buffer, it only mixes in 32 of the 64 bits available, > because the state buffer is an array of u32 values, even though 2 u32 > are expected to be filled (owing to the fact that it expects indexes 14 > and 15 to be filled). > > Bring the expected behavior into alignment by casting index 14 to an > unsignled long pointer, and xoring that in instead. > > Tested successfully by myself > > Signed-off-by: Neil Horman <nhor...@tuxdriver.com> > Reported-by: Steve Grubb <sgr...@redhat.com> > CC: "Theodore Ts'o" <ty...@mit.edu> > CC: Arnd Bergmann <a...@arndb.de> > CC: Greg Kroah-Hartman <gre...@linuxfoundation.org> > --- > drivers/char/random.c | 8 +++++--- > 1 file changed, 5 insertions(+), 3 deletions(-) > > diff --git a/drivers/char/random.c b/drivers/char/random.c > index 38c6d1af6d1c..8178618458ac 100644 > --- a/drivers/char/random.c > +++ b/drivers/char/random.c > @@ -975,14 +975,16 @@ static void _extract_crng(struct crng_state *crng, > __u8 out[CHACHA_BLOCK_SIZE]) > { > unsigned long v, flags; > - > + unsigned long *archrnd; > 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)) { > + archrnd = (unsigned long *)&crng->state[14]; > + *archrnd ^= v; > + } > chacha20_block(&crng->state[0], out); > if (crng->state[12] == 0) > crng->state[13]++; > -- > 2.20.1 > >
Ping, Arnd, Ted, Greg, any comment here? Neil