diff options
author | Theodore Ts'o <tytso@mit.edu> | 2014-06-10 22:46:37 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2014-07-15 04:49:39 -0400 |
commit | 91fcb532efe366d79b93a3c8c368b9dca6176a55 (patch) | |
tree | 3d2f571973e695ab5334abbaadbcad3a64152188 /drivers/char | |
parent | 1795cd9b3a91d4b5473c97f491d63892442212ab (diff) |
random: always update the entropy pool under the spinlock
Instead of using lockless techniques introduced in commit
902c098a3663, use spin_trylock to try to grab entropy pool's lock. If
we can't get the lock, then just try again on the next interrupt.
Based on discussions with George Spelvin.
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: George Spelvin <linux@horizon.com>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/random.c | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index 0a7ac0a7b252..922a2e4089f9 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -495,9 +495,8 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in, | |||
495 | tap4 = r->poolinfo->tap4; | 495 | tap4 = r->poolinfo->tap4; |
496 | tap5 = r->poolinfo->tap5; | 496 | tap5 = r->poolinfo->tap5; |
497 | 497 | ||
498 | smp_rmb(); | 498 | input_rotate = r->input_rotate; |
499 | input_rotate = ACCESS_ONCE(r->input_rotate); | 499 | i = r->add_ptr; |
500 | i = ACCESS_ONCE(r->add_ptr); | ||
501 | 500 | ||
502 | /* mix one byte at a time to simplify size handling and churn faster */ | 501 | /* mix one byte at a time to simplify size handling and churn faster */ |
503 | while (nbytes--) { | 502 | while (nbytes--) { |
@@ -524,9 +523,8 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in, | |||
524 | input_rotate = (input_rotate + (i ? 7 : 14)) & 31; | 523 | input_rotate = (input_rotate + (i ? 7 : 14)) & 31; |
525 | } | 524 | } |
526 | 525 | ||
527 | ACCESS_ONCE(r->input_rotate) = input_rotate; | 526 | r->input_rotate = input_rotate; |
528 | ACCESS_ONCE(r->add_ptr) = i; | 527 | r->add_ptr = i; |
529 | smp_wmb(); | ||
530 | 528 | ||
531 | if (out) | 529 | if (out) |
532 | for (j = 0; j < 16; j++) | 530 | for (j = 0; j < 16; j++) |
@@ -845,7 +843,7 @@ void add_interrupt_randomness(int irq, int irq_flags) | |||
845 | __u32 input[4], c_high, j_high; | 843 | __u32 input[4], c_high, j_high; |
846 | __u64 ip; | 844 | __u64 ip; |
847 | unsigned long seed; | 845 | unsigned long seed; |
848 | int credit; | 846 | int credit = 0; |
849 | 847 | ||
850 | c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0; | 848 | c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0; |
851 | j_high = (sizeof(now) > 4) ? now >> 32 : 0; | 849 | j_high = (sizeof(now) > 4) ? now >> 32 : 0; |
@@ -860,36 +858,40 @@ void add_interrupt_randomness(int irq, int irq_flags) | |||
860 | if ((fast_pool->count & 63) && !time_after(now, fast_pool->last + HZ)) | 858 | if ((fast_pool->count & 63) && !time_after(now, fast_pool->last + HZ)) |
861 | return; | 859 | return; |
862 | 860 | ||
863 | fast_pool->last = now; | ||
864 | |||
865 | r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; | 861 | r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; |
862 | if (!spin_trylock(&r->lock)) { | ||
863 | fast_pool->count--; | ||
864 | return; | ||
865 | } | ||
866 | fast_pool->last = now; | ||
866 | __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL); | 867 | __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL); |
867 | 868 | ||
868 | /* | 869 | /* |
870 | * If we have architectural seed generator, produce a seed and | ||
871 | * add it to the pool. For the sake of paranoia count it as | ||
872 | * 50% entropic. | ||
873 | */ | ||
874 | if (arch_get_random_seed_long(&seed)) { | ||
875 | __mix_pool_bytes(r, &seed, sizeof(seed), NULL); | ||
876 | credit += sizeof(seed) * 4; | ||
877 | } | ||
878 | spin_unlock(&r->lock); | ||
879 | |||
880 | /* | ||
869 | * If we don't have a valid cycle counter, and we see | 881 | * If we don't have a valid cycle counter, and we see |
870 | * back-to-back timer interrupts, then skip giving credit for | 882 | * back-to-back timer interrupts, then skip giving credit for |
871 | * any entropy, otherwise credit 1 bit. | 883 | * any entropy, otherwise credit 1 bit. |
872 | */ | 884 | */ |
873 | credit = 1; | 885 | credit++; |
874 | if (cycles == 0) { | 886 | if (cycles == 0) { |
875 | if (irq_flags & __IRQF_TIMER) { | 887 | if (irq_flags & __IRQF_TIMER) { |
876 | if (fast_pool->last_timer_intr) | 888 | if (fast_pool->last_timer_intr) |
877 | credit = 0; | 889 | credit--; |
878 | fast_pool->last_timer_intr = 1; | 890 | fast_pool->last_timer_intr = 1; |
879 | } else | 891 | } else |
880 | fast_pool->last_timer_intr = 0; | 892 | fast_pool->last_timer_intr = 0; |
881 | } | 893 | } |
882 | 894 | ||
883 | /* | ||
884 | * If we have architectural seed generator, produce a seed and | ||
885 | * add it to the pool. For the sake of paranoia count it as | ||
886 | * 50% entropic. | ||
887 | */ | ||
888 | if (arch_get_random_seed_long(&seed)) { | ||
889 | __mix_pool_bytes(r, &seed, sizeof(seed), NULL); | ||
890 | credit += sizeof(seed) * 4; | ||
891 | } | ||
892 | |||
893 | credit_entropy_bits(r, credit); | 895 | credit_entropy_bits(r, credit); |
894 | } | 896 | } |
895 | 897 | ||