diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-17 20:23:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-17 20:23:14 -0400 |
commit | 5ee22beeb25a5fa7fc6daf3597a8d9265f8c9ce1 (patch) | |
tree | 209058ef31be54ecdd8a023ed3fb531c3a939d33 /drivers/char | |
parent | 5cfb277d660b8b285fc831701e91f01ec933c7b4 (diff) | |
parent | e33ba5fa7afce1a9f159704121d4e4d110df8185 (diff) |
Merge tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random
Pull randomness bugfix from Ted Ts'o:
"random: fix entropy accounting bug introduced in v3.15"
* tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random:
random: fix nasty entropy accounting bug
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/random.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index 4ad71ef2cd59..0a7ac0a7b252 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -980,7 +980,6 @@ static void push_to_pool(struct work_struct *work) | |||
980 | static size_t account(struct entropy_store *r, size_t nbytes, int min, | 980 | static size_t account(struct entropy_store *r, size_t nbytes, int min, |
981 | int reserved) | 981 | int reserved) |
982 | { | 982 | { |
983 | int have_bytes; | ||
984 | int entropy_count, orig; | 983 | int entropy_count, orig; |
985 | size_t ibytes; | 984 | size_t ibytes; |
986 | 985 | ||
@@ -989,17 +988,19 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
989 | /* Can we pull enough? */ | 988 | /* Can we pull enough? */ |
990 | retry: | 989 | retry: |
991 | entropy_count = orig = ACCESS_ONCE(r->entropy_count); | 990 | entropy_count = orig = ACCESS_ONCE(r->entropy_count); |
992 | have_bytes = entropy_count >> (ENTROPY_SHIFT + 3); | ||
993 | ibytes = nbytes; | 991 | ibytes = nbytes; |
994 | /* If limited, never pull more than available */ | 992 | /* If limited, never pull more than available */ |
995 | if (r->limit) | 993 | if (r->limit) { |
996 | ibytes = min_t(size_t, ibytes, have_bytes - reserved); | 994 | int have_bytes = entropy_count >> (ENTROPY_SHIFT + 3); |
995 | |||
996 | if ((have_bytes -= reserved) < 0) | ||
997 | have_bytes = 0; | ||
998 | ibytes = min_t(size_t, ibytes, have_bytes); | ||
999 | } | ||
997 | if (ibytes < min) | 1000 | if (ibytes < min) |
998 | ibytes = 0; | 1001 | ibytes = 0; |
999 | if (have_bytes >= ibytes + reserved) | 1002 | if ((entropy_count -= ibytes << (ENTROPY_SHIFT + 3)) < 0) |
1000 | entropy_count -= ibytes << (ENTROPY_SHIFT + 3); | 1003 | entropy_count = 0; |
1001 | else | ||
1002 | entropy_count = reserved << (ENTROPY_SHIFT + 3); | ||
1003 | 1004 | ||
1004 | if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) | 1005 | if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) |
1005 | goto retry; | 1006 | goto retry; |