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

Configure Feed

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

random: only read from /dev/random after its pool has received 128 bits

Immediately after boot, we allow reads from /dev/random before its
entropy pool has been fully initialized. Fix this so that we don't
allow this until the blocking pool has received 128 bits.

We do this by repurposing the initialized flag in the entropy pool
struct, and use the initialized flag in the blocking pool to indicate
whether it is safe to pull from the blocking pool.

To do this, we needed to rework when we decide to push entropy from the
input pool to the blocking pool, since the initialized flag for the
input pool was used for this purpose. To simplify things, we no
longer use the initialized flag for that purpose, nor do we use the
entropy_total field any more.

Signed-off-by: Theodore Ts'o <tytso@mit.edu>

+27 -30
+22 -22
drivers/char/random.c
··· 470 470 unsigned short add_ptr; 471 471 unsigned short input_rotate; 472 472 int entropy_count; 473 - int entropy_total; 474 473 unsigned int initialized:1; 475 474 unsigned int last_data_init:1; 476 475 __u8 last_data[EXTRACT_SIZE]; ··· 642 643 */ 643 644 static void credit_entropy_bits(struct entropy_store *r, int nbits) 644 645 { 645 - int entropy_count, orig; 646 + int entropy_count, orig, has_initialized = 0; 646 647 const int pool_size = r->poolinfo->poolfracbits; 647 648 int nfrac = nbits << ENTROPY_SHIFT; 648 649 ··· 697 698 entropy_count = 0; 698 699 } else if (entropy_count > pool_size) 699 700 entropy_count = pool_size; 701 + if ((r == &blocking_pool) && !r->initialized && 702 + (entropy_count >> ENTROPY_SHIFT) > 128) 703 + has_initialized = 1; 700 704 if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) 701 705 goto retry; 702 706 703 - r->entropy_total += nbits; 704 - if (!r->initialized && r->entropy_total > 128) { 707 + if (has_initialized) 705 708 r->initialized = 1; 706 - r->entropy_total = 0; 707 - } 708 709 709 710 trace_credit_entropy_bits(r->name, nbits, 710 - entropy_count >> ENTROPY_SHIFT, 711 - r->entropy_total, _RET_IP_); 711 + entropy_count >> ENTROPY_SHIFT, _RET_IP_); 712 712 713 713 if (r == &input_pool) { 714 714 int entropy_bits = entropy_count >> ENTROPY_SHIFT; 715 + struct entropy_store *other = &blocking_pool; 715 716 716 - if (crng_init < 2 && entropy_bits >= 128) { 717 + if (crng_init < 2) { 718 + if (entropy_bits < 128) 719 + return; 717 720 crng_reseed(&primary_crng, r); 718 721 entropy_bits = r->entropy_count >> ENTROPY_SHIFT; 719 722 } ··· 726 725 wake_up_interruptible(&random_read_wait); 727 726 kill_fasync(&fasync, SIGIO, POLL_IN); 728 727 } 729 - /* If the input pool is getting full, send some 730 - * entropy to the blocking pool until it is 75% full. 728 + /* If the input pool is getting full, and the blocking 729 + * pool has room, send some entropy to the blocking 730 + * pool. 731 731 */ 732 - if (entropy_bits > random_write_wakeup_bits && 733 - r->initialized && 734 - r->entropy_total >= 2*random_read_wakeup_bits) { 735 - struct entropy_store *other = &blocking_pool; 736 - 737 - if (other->entropy_count <= 738 - 3 * other->poolinfo->poolfracbits / 4) { 739 - schedule_work(&other->push_work); 740 - r->entropy_total = 0; 741 - } 742 - } 732 + if (!work_pending(&other->push_work) && 733 + (ENTROPY_BITS(r) > 6 * r->poolinfo->poolbytes) && 734 + (ENTROPY_BITS(other) <= 6 * other->poolinfo->poolbytes)) 735 + schedule_work(&other->push_work); 743 736 } 744 737 } 745 738 ··· 1548 1553 int large_request = (nbytes > 256); 1549 1554 1550 1555 trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_); 1556 + if (!r->initialized && r->pull) { 1557 + xfer_secondary_pool(r, ENTROPY_BITS(r->pull)/8); 1558 + if (!r->initialized) 1559 + return 0; 1560 + } 1551 1561 xfer_secondary_pool(r, nbytes); 1552 1562 nbytes = account(r, nbytes, 0, 0); 1553 1563
+5 -8
include/trace/events/random.h
··· 62 62 63 63 TRACE_EVENT(credit_entropy_bits, 64 64 TP_PROTO(const char *pool_name, int bits, int entropy_count, 65 - int entropy_total, unsigned long IP), 65 + unsigned long IP), 66 66 67 - TP_ARGS(pool_name, bits, entropy_count, entropy_total, IP), 67 + TP_ARGS(pool_name, bits, entropy_count, IP), 68 68 69 69 TP_STRUCT__entry( 70 70 __field( const char *, pool_name ) 71 71 __field( int, bits ) 72 72 __field( int, entropy_count ) 73 - __field( int, entropy_total ) 74 73 __field(unsigned long, IP ) 75 74 ), 76 75 ··· 77 78 __entry->pool_name = pool_name; 78 79 __entry->bits = bits; 79 80 __entry->entropy_count = entropy_count; 80 - __entry->entropy_total = entropy_total; 81 81 __entry->IP = IP; 82 82 ), 83 83 84 - TP_printk("%s pool: bits %d entropy_count %d entropy_total %d " 85 - "caller %pS", __entry->pool_name, __entry->bits, 86 - __entry->entropy_count, __entry->entropy_total, 87 - (void *)__entry->IP) 84 + TP_printk("%s pool: bits %d entropy_count %d caller %pS", 85 + __entry->pool_name, __entry->bits, 86 + __entry->entropy_count, (void *)__entry->IP) 88 87 ); 89 88 90 89 TRACE_EVENT(push_to_pool,