diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/char/random.c | 44 |
1 files changed, 22 insertions, 22 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index 47ac7cd20fb1..e247c45b2772 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
| @@ -470,7 +470,6 @@ struct entropy_store { | |||
| 470 | unsigned short add_ptr; | 470 | unsigned short add_ptr; |
| 471 | unsigned short input_rotate; | 471 | unsigned short input_rotate; |
| 472 | int entropy_count; | 472 | int entropy_count; |
| 473 | int entropy_total; | ||
| 474 | unsigned int initialized:1; | 473 | unsigned int initialized:1; |
| 475 | unsigned int last_data_init:1; | 474 | unsigned int last_data_init:1; |
| 476 | __u8 last_data[EXTRACT_SIZE]; | 475 | __u8 last_data[EXTRACT_SIZE]; |
| @@ -643,7 +642,7 @@ static void process_random_ready_list(void) | |||
| 643 | */ | 642 | */ |
| 644 | static void credit_entropy_bits(struct entropy_store *r, int nbits) | 643 | static void credit_entropy_bits(struct entropy_store *r, int nbits) |
| 645 | { | 644 | { |
| 646 | int entropy_count, orig; | 645 | int entropy_count, orig, has_initialized = 0; |
| 647 | const int pool_size = r->poolinfo->poolfracbits; | 646 | const int pool_size = r->poolinfo->poolfracbits; |
| 648 | int nfrac = nbits << ENTROPY_SHIFT; | 647 | int nfrac = nbits << ENTROPY_SHIFT; |
| 649 | 648 | ||
| @@ -698,23 +697,25 @@ retry: | |||
| 698 | entropy_count = 0; | 697 | entropy_count = 0; |
| 699 | } else if (entropy_count > pool_size) | 698 | } else if (entropy_count > pool_size) |
| 700 | entropy_count = pool_size; | 699 | entropy_count = pool_size; |
| 700 | if ((r == &blocking_pool) && !r->initialized && | ||
| 701 | (entropy_count >> ENTROPY_SHIFT) > 128) | ||
| 702 | has_initialized = 1; | ||
| 701 | if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) | 703 | if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) |
| 702 | goto retry; | 704 | goto retry; |
| 703 | 705 | ||
| 704 | r->entropy_total += nbits; | 706 | if (has_initialized) |
| 705 | if (!r->initialized && r->entropy_total > 128) { | ||
| 706 | r->initialized = 1; | 707 | r->initialized = 1; |
| 707 | r->entropy_total = 0; | ||
| 708 | } | ||
| 709 | 708 | ||
| 710 | trace_credit_entropy_bits(r->name, nbits, | 709 | trace_credit_entropy_bits(r->name, nbits, |
| 711 | entropy_count >> ENTROPY_SHIFT, | 710 | entropy_count >> ENTROPY_SHIFT, _RET_IP_); |
| 712 | r->entropy_total, _RET_IP_); | ||
| 713 | 711 | ||
| 714 | if (r == &input_pool) { | 712 | if (r == &input_pool) { |
| 715 | int entropy_bits = entropy_count >> ENTROPY_SHIFT; | 713 | int entropy_bits = entropy_count >> ENTROPY_SHIFT; |
| 714 | struct entropy_store *other = &blocking_pool; | ||
| 716 | 715 | ||
| 717 | if (crng_init < 2 && entropy_bits >= 128) { | 716 | if (crng_init < 2) { |
| 717 | if (entropy_bits < 128) | ||
| 718 | return; | ||
| 718 | crng_reseed(&primary_crng, r); | 719 | crng_reseed(&primary_crng, r); |
| 719 | entropy_bits = r->entropy_count >> ENTROPY_SHIFT; | 720 | entropy_bits = r->entropy_count >> ENTROPY_SHIFT; |
| 720 | } | 721 | } |
| @@ -725,20 +726,14 @@ retry: | |||
| 725 | wake_up_interruptible(&random_read_wait); | 726 | wake_up_interruptible(&random_read_wait); |
| 726 | kill_fasync(&fasync, SIGIO, POLL_IN); | 727 | kill_fasync(&fasync, SIGIO, POLL_IN); |
| 727 | } | 728 | } |
| 728 | /* If the input pool is getting full, send some | 729 | /* If the input pool is getting full, and the blocking |
| 729 | * entropy to the blocking pool until it is 75% full. | 730 | * pool has room, send some entropy to the blocking |
| 731 | * pool. | ||
| 730 | */ | 732 | */ |
| 731 | if (entropy_bits > random_write_wakeup_bits && | 733 | if (!work_pending(&other->push_work) && |
| 732 | r->initialized && | 734 | (ENTROPY_BITS(r) > 6 * r->poolinfo->poolbytes) && |
| 733 | r->entropy_total >= 2*random_read_wakeup_bits) { | 735 | (ENTROPY_BITS(other) <= 6 * other->poolinfo->poolbytes)) |
| 734 | struct entropy_store *other = &blocking_pool; | 736 | schedule_work(&other->push_work); |
| 735 | |||
| 736 | if (other->entropy_count <= | ||
| 737 | 3 * other->poolinfo->poolfracbits / 4) { | ||
| 738 | schedule_work(&other->push_work); | ||
| 739 | r->entropy_total = 0; | ||
| 740 | } | ||
| 741 | } | ||
| 742 | } | 737 | } |
| 743 | } | 738 | } |
| 744 | 739 | ||
| @@ -1553,6 +1548,11 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, | |||
| 1553 | int large_request = (nbytes > 256); | 1548 | int large_request = (nbytes > 256); |
| 1554 | 1549 | ||
| 1555 | trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_); | 1550 | trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_); |
| 1551 | if (!r->initialized && r->pull) { | ||
| 1552 | xfer_secondary_pool(r, ENTROPY_BITS(r->pull)/8); | ||
| 1553 | if (!r->initialized) | ||
| 1554 | return 0; | ||
| 1555 | } | ||
| 1556 | xfer_secondary_pool(r, nbytes); | 1556 | xfer_secondary_pool(r, nbytes); |
| 1557 | nbytes = account(r, nbytes, 0, 0); | 1557 | nbytes = account(r, nbytes, 0, 0); |
| 1558 | 1558 | ||
