diff options
Diffstat (limited to 'drivers/char/random.c')
| -rw-r--r-- | drivers/char/random.c | 54 |
1 files changed, 31 insertions, 23 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index cd9a6211dcad..35487e8ded59 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
| @@ -865,16 +865,24 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
| 865 | if (r->entropy_count / 8 < min + reserved) { | 865 | if (r->entropy_count / 8 < min + reserved) { |
| 866 | nbytes = 0; | 866 | nbytes = 0; |
| 867 | } else { | 867 | } else { |
| 868 | int entropy_count, orig; | ||
| 869 | retry: | ||
| 870 | entropy_count = orig = ACCESS_ONCE(r->entropy_count); | ||
| 868 | /* If limited, never pull more than available */ | 871 | /* If limited, never pull more than available */ |
| 869 | if (r->limit && nbytes + reserved >= r->entropy_count / 8) | 872 | if (r->limit && nbytes + reserved >= entropy_count / 8) |
| 870 | nbytes = r->entropy_count/8 - reserved; | 873 | nbytes = entropy_count/8 - reserved; |
| 871 | 874 | ||
| 872 | if (r->entropy_count / 8 >= nbytes + reserved) | 875 | if (entropy_count / 8 >= nbytes + reserved) { |
| 873 | r->entropy_count -= nbytes*8; | 876 | entropy_count -= nbytes*8; |
| 874 | else | 877 | if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) |
| 875 | r->entropy_count = reserved; | 878 | goto retry; |
| 879 | } else { | ||
| 880 | entropy_count = reserved; | ||
| 881 | if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) | ||
| 882 | goto retry; | ||
| 883 | } | ||
| 876 | 884 | ||
| 877 | if (r->entropy_count < random_write_wakeup_thresh) | 885 | if (entropy_count < random_write_wakeup_thresh) |
| 878 | wakeup_write = 1; | 886 | wakeup_write = 1; |
| 879 | } | 887 | } |
| 880 | 888 | ||
| @@ -957,10 +965,23 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
| 957 | { | 965 | { |
| 958 | ssize_t ret = 0, i; | 966 | ssize_t ret = 0, i; |
| 959 | __u8 tmp[EXTRACT_SIZE]; | 967 | __u8 tmp[EXTRACT_SIZE]; |
| 968 | unsigned long flags; | ||
| 960 | 969 | ||
| 961 | /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ | 970 | /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ |
| 962 | if (fips_enabled && !r->last_data_init) | 971 | if (fips_enabled) { |
| 963 | nbytes += EXTRACT_SIZE; | 972 | spin_lock_irqsave(&r->lock, flags); |
| 973 | if (!r->last_data_init) { | ||
| 974 | r->last_data_init = true; | ||
| 975 | spin_unlock_irqrestore(&r->lock, flags); | ||
| 976 | trace_extract_entropy(r->name, EXTRACT_SIZE, | ||
| 977 | r->entropy_count, _RET_IP_); | ||
| 978 | xfer_secondary_pool(r, EXTRACT_SIZE); | ||
| 979 | extract_buf(r, tmp); | ||
| 980 | spin_lock_irqsave(&r->lock, flags); | ||
| 981 | memcpy(r->last_data, tmp, EXTRACT_SIZE); | ||
| 982 | } | ||
| 983 | spin_unlock_irqrestore(&r->lock, flags); | ||
| 984 | } | ||
| 964 | 985 | ||
| 965 | trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); | 986 | trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); |
| 966 | xfer_secondary_pool(r, nbytes); | 987 | xfer_secondary_pool(r, nbytes); |
| @@ -970,19 +991,6 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
| 970 | extract_buf(r, tmp); | 991 | extract_buf(r, tmp); |
| 971 | 992 | ||
| 972 | if (fips_enabled) { | 993 | if (fips_enabled) { |
| 973 | unsigned long flags; | ||
| 974 | |||
| 975 | |||
| 976 | /* prime last_data value if need be, per fips 140-2 */ | ||
| 977 | if (!r->last_data_init) { | ||
| 978 | spin_lock_irqsave(&r->lock, flags); | ||
| 979 | memcpy(r->last_data, tmp, EXTRACT_SIZE); | ||
| 980 | r->last_data_init = true; | ||
| 981 | nbytes -= EXTRACT_SIZE; | ||
| 982 | spin_unlock_irqrestore(&r->lock, flags); | ||
| 983 | extract_buf(r, tmp); | ||
| 984 | } | ||
| 985 | |||
| 986 | spin_lock_irqsave(&r->lock, flags); | 994 | spin_lock_irqsave(&r->lock, flags); |
| 987 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) | 995 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) |
| 988 | panic("Hardware RNG duplicated output!\n"); | 996 | panic("Hardware RNG duplicated output!\n"); |
