diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2014-03-17 19:36:29 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2014-03-19 22:22:06 -0400 |
commit | 331c6490c7f10dcf263712e313b7c0bc7fb6d77a (patch) | |
tree | 30249a0a1a7dc7ea7538fe622a4303bb26853f32 /drivers/char | |
parent | 83664a6928a420b5ccfc0cf23ddbfe3634fea271 (diff) |
random: If we have arch_get_random_seed*(), try it before blocking
If we have arch_get_random_seed*(), try to use it for emergency refill
of the entropy pool before giving up and blocking on /dev/random. It
may or may not work in the moment, but if it does work, it will give
the user better service than blocking will.
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/random.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index a4bea7775e0f..c35cee268e13 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -1294,6 +1294,34 @@ void rand_initialize_disk(struct gendisk *disk) | |||
1294 | } | 1294 | } |
1295 | #endif | 1295 | #endif |
1296 | 1296 | ||
1297 | /* | ||
1298 | * Attempt an emergency refill using arch_get_random_seed_long(). | ||
1299 | * | ||
1300 | * As with add_interrupt_randomness() be paranoid and only | ||
1301 | * credit the output as 50% entropic. | ||
1302 | */ | ||
1303 | static int arch_random_refill(void) | ||
1304 | { | ||
1305 | const unsigned int nlongs = 64; /* Arbitrary number */ | ||
1306 | unsigned int n = 0; | ||
1307 | unsigned int i; | ||
1308 | unsigned long buf[nlongs]; | ||
1309 | |||
1310 | for (i = 0; i < nlongs; i++) { | ||
1311 | if (arch_get_random_seed_long(&buf[n])) | ||
1312 | n++; | ||
1313 | } | ||
1314 | |||
1315 | if (n) { | ||
1316 | unsigned int rand_bytes = n * sizeof(unsigned long); | ||
1317 | |||
1318 | mix_pool_bytes(&input_pool, buf, rand_bytes, NULL); | ||
1319 | credit_entropy_bits(&input_pool, rand_bytes*4); | ||
1320 | } | ||
1321 | |||
1322 | return n; | ||
1323 | } | ||
1324 | |||
1297 | static ssize_t | 1325 | static ssize_t |
1298 | random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | 1326 | random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) |
1299 | { | 1327 | { |
@@ -1312,8 +1340,13 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | |||
1312 | ENTROPY_BITS(&input_pool)); | 1340 | ENTROPY_BITS(&input_pool)); |
1313 | if (n > 0) | 1341 | if (n > 0) |
1314 | return n; | 1342 | return n; |
1343 | |||
1315 | /* Pool is (near) empty. Maybe wait and retry. */ | 1344 | /* Pool is (near) empty. Maybe wait and retry. */ |
1316 | 1345 | ||
1346 | /* First try an emergency refill */ | ||
1347 | if (arch_random_refill()) | ||
1348 | continue; | ||
1349 | |||
1317 | if (file->f_flags & O_NONBLOCK) | 1350 | if (file->f_flags & O_NONBLOCK) |
1318 | return -EAGAIN; | 1351 | return -EAGAIN; |
1319 | 1352 | ||