mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 05:02:12 +00:00
Random number generator fixes for Linux 5.18-rc3.
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEq5lC5tSkz8NBJiCnSfxwEqXeA64FAmJavk0ACgkQSfxwEqXe A640KA/9FHngPjK8AOuFJJRfdNYu5CWcn4PD/xmYGhP1QUuKOfIF6rUGrl7w4jCh +mKICOt2Rt2ZqSscS1ccpddiwAcoURrra6pW8Oo5IiuHlPBWR/jow9FzeLZpP4II 5mcWSZX4/MJFs9o6T+25FE9tPjsVcEi1hgYEU0ecXtXYK+mIUbPobF1pWlI+C61F 8sYQ4GrpJHLWreou7SYfzbI3siaXmewie8aYgrqvU8Bt7U2UVTA0j8VxeX7+r87/ xZ+/n+E3WOiEt2h0UyOB6+5bIL0t6qJI/plc8kQN/R5UHSoMrT06MdwrThI4exI3 YDDf488aKiYPdeQt3kFXH4o1PVK9R072Z+ZK63jfUxGOQs1DXI2DxCSqgO3fPfIR v9uy0kG6zWG+C8RuX3VV12gIL6/XOFRx7UHVwSnt+A1Li/DPEdNoYlKesSGOKuel vbXBmed2z5v02KMd1Y9LtrioLco8JDFYD0OEtbEaGjv7Kt+EcVtapo1e7N2VSmk6 IKxp7soEorJSR13rR5vyeF+yOZmxn6BOePc7m48O0Wqx76DHlyXiMPNTJUrHIC2z XfD8+P1mHA2Iz71T7YI9Dmzw9uIVZuUteiEpvc0o/uy8z3YzOUftnqQBsAKwbxz5 HKrIdkocQNbXK46GKpjK6OY8BCwOeRM+z/XdJwYDek7G1+1ULpg= =2JCC -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
92edbe32e3
@ -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
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user