Skip to content

Commit

Permalink
Merge tag 'random-5.18-rc3-for-linus' of git://git.kernel.org/pub/scm…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
Linus Torvalds committed Apr 16, 2022
2 parents 90ea17a + 35a33ff commit 92edbe3
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 25 deletions.
44 changes: 20 additions & 24 deletions drivers/char/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

Expand Down Expand Up @@ -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];

Expand All @@ -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;
}

/*
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion include/linux/timex.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

/*
Expand Down

0 comments on commit 92edbe3

Please sign in to comment.