Skip to content

Commit 2bbb698

Browse files
Harald Freudenbergerherbertx
authored andcommitted
hwrng: use rng source with best quality
This patch rewoks the hwrng to always use the rng source with best entropy quality. On registation and unregistration the hwrng now tries to choose the best (= highest quality value) rng source. The handling of the internal list of registered rng sources is now always sorted by quality and the top most rng chosen. Signed-off-by: Harald Freudenberger <[email protected]> Reviewed-by: PrasannaKumar Muralidharan <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent ad81808 commit 2bbb698

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

drivers/char/hw_random/core.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
static struct hwrng *current_rng;
3131
static struct task_struct *hwrng_fill;
32+
/* list of registered rngs, sorted decending by quality */
3233
static LIST_HEAD(rng_list);
3334
/* Protects rng_list and current_rng */
3435
static DEFINE_MUTEX(rng_mutex);
@@ -417,6 +418,7 @@ int hwrng_register(struct hwrng *rng)
417418
{
418419
int err = -EINVAL;
419420
struct hwrng *old_rng, *tmp;
421+
struct list_head *rng_list_ptr;
420422

421423
if (!rng->name || (!rng->data_read && !rng->read))
422424
goto out;
@@ -432,14 +434,25 @@ int hwrng_register(struct hwrng *rng)
432434
init_completion(&rng->cleanup_done);
433435
complete(&rng->cleanup_done);
434436

437+
/* rng_list is sorted by decreasing quality */
438+
list_for_each(rng_list_ptr, &rng_list) {
439+
tmp = list_entry(rng_list_ptr, struct hwrng, list);
440+
if (tmp->quality < rng->quality)
441+
break;
442+
}
443+
list_add_tail(&rng->list, rng_list_ptr);
444+
435445
old_rng = current_rng;
436446
err = 0;
437-
if (!old_rng) {
447+
if (!old_rng || (rng->quality > old_rng->quality)) {
448+
/*
449+
* Set new rng as current as the new rng source
450+
* provides better entropy quality.
451+
*/
438452
err = set_current_rng(rng);
439453
if (err)
440454
goto out_unlock;
441455
}
442-
list_add_tail(&rng->list, &rng_list);
443456

444457
if (old_rng && !rng->init) {
445458
/*
@@ -466,12 +479,12 @@ void hwrng_unregister(struct hwrng *rng)
466479
list_del(&rng->list);
467480
if (current_rng == rng) {
468481
drop_current_rng();
482+
/* rng_list is sorted by quality, use the best (=first) one */
469483
if (!list_empty(&rng_list)) {
470-
struct hwrng *tail;
471-
472-
tail = list_entry(rng_list.prev, struct hwrng, list);
484+
struct hwrng *new_rng;
473485

474-
set_current_rng(tail);
486+
new_rng = list_entry(rng_list.next, struct hwrng, list);
487+
set_current_rng(new_rng);
475488
}
476489
}
477490

0 commit comments

Comments
 (0)