Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+21 -25
+20 -24
drivers/char/random.c
··· 333 333 chacha20_block(chacha_state, first_block); 334 334 335 335 memcpy(key, first_block, CHACHA_KEY_SIZE); 336 - memcpy(random_data, first_block + CHACHA_KEY_SIZE, random_data_len); 336 + memmove(random_data, first_block + CHACHA_KEY_SIZE, random_data_len); 337 337 memzero_explicit(first_block, sizeof(first_block)); 338 338 } 339 339 ··· 523 523 524 524 static ssize_t get_random_bytes_user(void __user *buf, size_t nbytes) 525 525 { 526 - ssize_t ret = 0; 527 - size_t len; 526 + size_t len, left, ret = 0; 528 527 u32 chacha_state[CHACHA_STATE_WORDS]; 529 528 u8 output[CHACHA_BLOCK_SIZE]; 530 529 ··· 542 543 * the user directly. 543 544 */ 544 545 if (nbytes <= CHACHA_KEY_SIZE) { 545 - ret = copy_to_user(buf, &chacha_state[4], nbytes) ? -EFAULT : nbytes; 546 + ret = nbytes - copy_to_user(buf, &chacha_state[4], nbytes); 546 547 goto out_zero_chacha; 547 548 } 548 549 549 - do { 550 + for (;;) { 550 551 chacha20_block(chacha_state, output); 551 552 if (unlikely(chacha_state[12] == 0)) 552 553 ++chacha_state[13]; 553 554 554 555 len = min_t(size_t, nbytes, CHACHA_BLOCK_SIZE); 555 - if (copy_to_user(buf, output, len)) { 556 - ret = -EFAULT; 556 + left = copy_to_user(buf, output, len); 557 + if (left) { 558 + ret += len - left; 557 559 break; 558 560 } 559 561 560 - nbytes -= len; 561 562 buf += len; 562 563 ret += len; 564 + nbytes -= len; 565 + if (!nbytes) 566 + break; 563 567 564 568 BUILD_BUG_ON(PAGE_SIZE % CHACHA_BLOCK_SIZE != 0); 565 - if (!(ret % PAGE_SIZE) && nbytes) { 569 + if (ret % PAGE_SIZE == 0) { 566 570 if (signal_pending(current)) 567 571 break; 568 572 cond_resched(); 569 573 } 570 - } while (nbytes); 574 + } 571 575 572 576 memzero_explicit(output, sizeof(output)); 573 577 out_zero_chacha: 574 578 memzero_explicit(chacha_state, sizeof(chacha_state)); 575 - return ret; 579 + return ret ? ret : -EFAULT; 576 580 } 577 581 578 582 /* ··· 1018 1016 */ 1019 1017 void add_device_randomness(const void *buf, size_t size) 1020 1018 { 1021 - cycles_t cycles = random_get_entropy(); 1019 + unsigned long cycles = random_get_entropy(); 1022 1020 unsigned long flags, now = jiffies; 1023 1021 1024 1022 if (crng_init == 0 && size) ··· 1049 1047 */ 1050 1048 static void add_timer_randomness(struct timer_rand_state *state, unsigned int num) 1051 1049 { 1052 - cycles_t cycles = random_get_entropy(); 1053 - unsigned long flags, now = jiffies; 1050 + unsigned long cycles = random_get_entropy(), now = jiffies, flags; 1054 1051 long delta, delta2, delta3; 1055 1052 1056 1053 spin_lock_irqsave(&input_pool.lock, flags); ··· 1338 1337 void add_interrupt_randomness(int irq) 1339 1338 { 1340 1339 enum { MIX_INFLIGHT = 1U << 31 }; 1341 - cycles_t cycles = random_get_entropy(); 1342 - unsigned long now = jiffies; 1340 + unsigned long cycles = random_get_entropy(), now = jiffies; 1343 1341 struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness); 1344 1342 struct pt_regs *regs = get_irq_regs(); 1345 1343 unsigned int new_count; ··· 1351 1351 if (cycles == 0) 1352 1352 cycles = get_reg(fast_pool, regs); 1353 1353 1354 - if (sizeof(cycles) == 8) 1354 + if (sizeof(unsigned long) == 8) { 1355 1355 irq_data.u64[0] = cycles ^ rol64(now, 32) ^ irq; 1356 - else { 1356 + irq_data.u64[1] = regs ? instruction_pointer(regs) : _RET_IP_; 1357 + } else { 1357 1358 irq_data.u32[0] = cycles ^ irq; 1358 1359 irq_data.u32[1] = now; 1359 - } 1360 - 1361 - if (sizeof(unsigned long) == 8) 1362 - irq_data.u64[1] = regs ? instruction_pointer(regs) : _RET_IP_; 1363 - else { 1364 1360 irq_data.u32[2] = regs ? instruction_pointer(regs) : _RET_IP_; 1365 1361 irq_data.u32[3] = get_reg(fast_pool, regs); 1366 1362 } ··· 1403 1407 static void try_to_generate_entropy(void) 1404 1408 { 1405 1409 struct { 1406 - cycles_t cycles; 1410 + unsigned long cycles; 1407 1411 struct timer_list timer; 1408 1412 } stack; 1409 1413
+1 -1
include/linux/timex.h
··· 75 75 * By default we use get_cycles() for this purpose, but individual 76 76 * architectures may override this in their asm/timex.h header file. 77 77 */ 78 - #define random_get_entropy() get_cycles() 78 + #define random_get_entropy() ((unsigned long)get_cycles()) 79 79 #endif 80 80 81 81 /*