Skip to content

Commit

Permalink
random: unify cycles_t and jiffies usage and types
Browse files Browse the repository at this point in the history
commit abded93 upstream.

random_get_entropy() returns a cycles_t, not an unsigned long, which is
sometimes 64 bits on various 32-bit platforms, including x86.
Conversely, jiffies is always unsigned long. This commit fixes things to
use cycles_t for fields that use random_get_entropy(), named "cycles",
and unsigned long for fields that use jiffies, named "now". It's also
good to mix in a cycles_t and a jiffies in the same way for both
add_device_randomness and add_timer_randomness, rather than using xor in
one case. Finally, we unify the order of these volatile reads, always
reading the more precise cycles counter, and then jiffies, so that the
cycle counter is as close to the event as possible.

Cc: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
zx2c4 authored and gregkh committed May 30, 2022
1 parent 47f0e89 commit 192d4c6
Showing 1 changed file with 27 additions and 29 deletions.
56 changes: 27 additions & 29 deletions drivers/char/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -1020,12 +1020,6 @@ int __init rand_initialize(void)
return 0;
}

/* There is one of these per entropy source */
struct timer_rand_state {
cycles_t last_time;
long last_delta, last_delta2;
};

/*
* Add device- or boot-specific data to the input pool to help
* initialize it.
Expand All @@ -1036,19 +1030,26 @@ struct timer_rand_state {
*/
void add_device_randomness(const void *buf, size_t size)
{
unsigned long time = random_get_entropy() ^ jiffies;
unsigned long flags;
cycles_t cycles = random_get_entropy();
unsigned long flags, now = jiffies;

if (crng_init == 0 && size)
crng_pre_init_inject(buf, size, false, false);

spin_lock_irqsave(&input_pool.lock, flags);
_mix_pool_bytes(&cycles, sizeof(cycles));
_mix_pool_bytes(&now, sizeof(now));
_mix_pool_bytes(buf, size);
_mix_pool_bytes(&time, sizeof(time));
spin_unlock_irqrestore(&input_pool.lock, flags);
}
EXPORT_SYMBOL(add_device_randomness);

/* There is one of these per entropy source */
struct timer_rand_state {
unsigned long last_time;
long last_delta, last_delta2;
};

/*
* This function adds entropy to the entropy "pool" by using timing
* delays. It uses the timer_rand_state structure to make an estimate
Expand All @@ -1057,29 +1058,26 @@ EXPORT_SYMBOL(add_device_randomness);
* The number "num" is also added to the pool - it should somehow describe
* the type of event which just happened. This is currently 0-255 for
* keyboard scan codes, and 256 upwards for interrupts.
*
*/
static void add_timer_randomness(struct timer_rand_state *state, unsigned int num)
{
struct {
long jiffies;
unsigned int cycles;
unsigned int num;
} sample;
cycles_t cycles = random_get_entropy();
unsigned long flags, now = jiffies;
long delta, delta2, delta3;

sample.jiffies = jiffies;
sample.cycles = random_get_entropy();
sample.num = num;
mix_pool_bytes(&sample, sizeof(sample));
spin_lock_irqsave(&input_pool.lock, flags);
_mix_pool_bytes(&cycles, sizeof(cycles));
_mix_pool_bytes(&now, sizeof(now));
_mix_pool_bytes(&num, sizeof(num));
spin_unlock_irqrestore(&input_pool.lock, flags);

/*
* Calculate number of bits of randomness we probably added.
* We take into account the first, second and third-order deltas
* in order to make our estimate.
*/
delta = sample.jiffies - READ_ONCE(state->last_time);
WRITE_ONCE(state->last_time, sample.jiffies);
delta = now - READ_ONCE(state->last_time);
WRITE_ONCE(state->last_time, now);

delta2 = delta - READ_ONCE(state->last_delta);
WRITE_ONCE(state->last_delta, delta);
Expand Down Expand Up @@ -1305,10 +1303,10 @@ static void mix_interrupt_randomness(struct work_struct *work)
void add_interrupt_randomness(int irq)
{
enum { MIX_INFLIGHT = 1U << 31 };
cycles_t cycles = random_get_entropy();
unsigned long now = jiffies;
struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
struct pt_regs *regs = get_irq_regs();
unsigned long now = jiffies;
cycles_t cycles = random_get_entropy();
unsigned int new_count;

if (cycles == 0)
Expand Down Expand Up @@ -1383,28 +1381,28 @@ static void entropy_timer(struct timer_list *t)
static void try_to_generate_entropy(void)
{
struct {
unsigned long now;
cycles_t cycles;
struct timer_list timer;
} stack;

stack.now = random_get_entropy();
stack.cycles = random_get_entropy();

/* Slow counter - or none. Don't even bother */
if (stack.now == random_get_entropy())
if (stack.cycles == random_get_entropy())
return;

timer_setup_on_stack(&stack.timer, entropy_timer, 0);
while (!crng_ready()) {
if (!timer_pending(&stack.timer))
mod_timer(&stack.timer, jiffies + 1);
mix_pool_bytes(&stack.now, sizeof(stack.now));
mix_pool_bytes(&stack.cycles, sizeof(stack.cycles));
schedule();
stack.now = random_get_entropy();
stack.cycles = random_get_entropy();
}

del_timer_sync(&stack.timer);
destroy_timer_on_stack(&stack.timer);
mix_pool_bytes(&stack.now, sizeof(stack.now));
mix_pool_bytes(&stack.cycles, sizeof(stack.cycles));
}


Expand Down

0 comments on commit 192d4c6

Please sign in to comment.