Commit 92edbe32 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'random-5.18-rc3-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/crng/random

Pull random number generator fixes from Jason Donenfeld:

 - Per your suggestion, random reads now won't fail if there's a page
   fault after some non-zero amount of data has been read, which makes
   the behavior consistent with all other reads in the kernel.

 - Rather than an inconsistent mix of random_get_entropy() returning an
   unsigned long or a cycles_t, now it just returns an unsigned long.

 - A memcpy() was replaced with an memmove(), because the addresses are
   sometimes overlapping. In practice the destination is always before
   the source, so not really an issue, but better to be correct than
   not.

* tag 'random-5.18-rc3-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/crng/random:
  random: use memmove instead of memcpy for remaining 32 bytes
  random: make random_get_entropy() return an unsigned long
  random: allow partial reads if later user copies fail
parents 90ea17a9 35a33ff3
......@@ -333,7 +333,7 @@ static void crng_fast_key_erasure(u8 key[CHACHA_KEY_SIZE],
chacha20_block(chacha_state, first_block);
memcpy(key, first_block, CHACHA_KEY_SIZE);
memcpy(random_data, first_block + CHACHA_KEY_SIZE, random_data_len);
memmove(random_data, first_block + CHACHA_KEY_SIZE, random_data_len);
memzero_explicit(first_block, sizeof(first_block));
}
......@@ -523,8 +523,7 @@ EXPORT_SYMBOL(get_random_bytes);
static ssize_t get_random_bytes_user(void __user *buf, size_t nbytes)
{
ssize_t ret = 0;
size_t len;
size_t len, left, ret = 0;
u32 chacha_state[CHACHA_STATE_WORDS];
u8 output[CHACHA_BLOCK_SIZE];
......@@ -543,37 +542,40 @@ static ssize_t get_random_bytes_user(void __user *buf, size_t nbytes)
* the user directly.
*/
if (nbytes <= CHACHA_KEY_SIZE) {
ret = copy_to_user(buf, &chacha_state[4], nbytes) ? -EFAULT : nbytes;
ret = nbytes - copy_to_user(buf, &chacha_state[4], nbytes);
goto out_zero_chacha;
}
do {
for (;;) {
chacha20_block(chacha_state, output);
if (unlikely(chacha_state[12] == 0))
++chacha_state[13];
len = min_t(size_t, nbytes, CHACHA_BLOCK_SIZE);
if (copy_to_user(buf, output, len)) {
ret = -EFAULT;
left = copy_to_user(buf, output, len);
if (left) {
ret += len - left;
break;
}
nbytes -= len;
buf += len;
ret += len;
nbytes -= len;
if (!nbytes)
break;
BUILD_BUG_ON(PAGE_SIZE % CHACHA_BLOCK_SIZE != 0);
if (!(ret % PAGE_SIZE) && nbytes) {
if (ret % PAGE_SIZE == 0) {
if (signal_pending(current))
break;
cond_resched();
}
} while (nbytes);
}
memzero_explicit(output, sizeof(output));
out_zero_chacha:
memzero_explicit(chacha_state, sizeof(chacha_state));
return ret;
return ret ? ret : -EFAULT;
}
/*
......@@ -1016,7 +1018,7 @@ int __init rand_initialize(void)
*/
void add_device_randomness(const void *buf, size_t size)
{
cycles_t cycles = random_get_entropy();
unsigned long cycles = random_get_entropy();
unsigned long flags, now = jiffies;
if (crng_init == 0 && size)
......@@ -1047,8 +1049,7 @@ struct timer_rand_state {
*/
static void add_timer_randomness(struct timer_rand_state *state, unsigned int num)
{
cycles_t cycles = random_get_entropy();
unsigned long flags, now = jiffies;
unsigned long cycles = random_get_entropy(), now = jiffies, flags;
long delta, delta2, delta3;
spin_lock_irqsave(&input_pool.lock, flags);
......@@ -1337,8 +1338,7 @@ 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;
unsigned long cycles = random_get_entropy(), now = jiffies;
struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
struct pt_regs *regs = get_irq_regs();
unsigned int new_count;
......@@ -1351,16 +1351,12 @@ void add_interrupt_randomness(int irq)
if (cycles == 0)
cycles = get_reg(fast_pool, regs);
if (sizeof(cycles) == 8)
if (sizeof(unsigned long) == 8) {
irq_data.u64[0] = cycles ^ rol64(now, 32) ^ irq;
else {
irq_data.u64[1] = regs ? instruction_pointer(regs) : _RET_IP_;
} else {
irq_data.u32[0] = cycles ^ irq;
irq_data.u32[1] = now;
}
if (sizeof(unsigned long) == 8)
irq_data.u64[1] = regs ? instruction_pointer(regs) : _RET_IP_;
else {
irq_data.u32[2] = regs ? instruction_pointer(regs) : _RET_IP_;
irq_data.u32[3] = get_reg(fast_pool, regs);
}
......@@ -1407,7 +1403,7 @@ static void entropy_timer(struct timer_list *t)
static void try_to_generate_entropy(void)
{
struct {
cycles_t cycles;
unsigned long cycles;
struct timer_list timer;
} stack;
......
......@@ -75,7 +75,7 @@
* By default we use get_cycles() for this purpose, but individual
* architectures may override this in their asm/timex.h header file.
*/
#define random_get_entropy() get_cycles()
#define random_get_entropy() ((unsigned long)get_cycles())
#endif
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment