.. | .. |
---|
4 | 4 | * Copyright 2006 Michael Buesch <m@bues.ch> |
---|
5 | 5 | * Copyright 2005 (c) MontaVista Software, Inc. |
---|
6 | 6 | * |
---|
7 | | - * Please read Documentation/hw_random.txt for details on use. |
---|
| 7 | + * Please read Documentation/admin-guide/hw_random.rst for details on use. |
---|
8 | 8 | * |
---|
9 | 9 | * This software may be used and distributed according to the terms |
---|
10 | 10 | * of the GNU General Public License, incorporated herein by reference. |
---|
.. | .. |
---|
15 | 15 | #include <linux/err.h> |
---|
16 | 16 | #include <linux/fs.h> |
---|
17 | 17 | #include <linux/hw_random.h> |
---|
| 18 | +#include <linux/random.h> |
---|
18 | 19 | #include <linux/kernel.h> |
---|
19 | 20 | #include <linux/kthread.h> |
---|
20 | 21 | #include <linux/sched/signal.h> |
---|
.. | .. |
---|
44 | 45 | |
---|
45 | 46 | module_param(current_quality, ushort, 0644); |
---|
46 | 47 | MODULE_PARM_DESC(current_quality, |
---|
47 | | - "current hwrng entropy estimation per mill"); |
---|
| 48 | + "current hwrng entropy estimation per 1024 bits of input"); |
---|
48 | 49 | module_param(default_quality, ushort, 0644); |
---|
49 | 50 | MODULE_PARM_DESC(default_quality, |
---|
50 | | - "default entropy content of hwrng per mill"); |
---|
| 51 | + "default entropy content of hwrng per 1024 bits of input"); |
---|
51 | 52 | |
---|
52 | 53 | static void drop_current_rng(void); |
---|
53 | 54 | static int hwrng_init(struct hwrng *rng); |
---|
.. | .. |
---|
111 | 112 | } |
---|
112 | 113 | |
---|
113 | 114 | /* Returns ERR_PTR(), NULL or refcounted hwrng */ |
---|
| 115 | +static struct hwrng *get_current_rng_nolock(void) |
---|
| 116 | +{ |
---|
| 117 | + if (current_rng) |
---|
| 118 | + kref_get(¤t_rng->ref); |
---|
| 119 | + |
---|
| 120 | + return current_rng; |
---|
| 121 | +} |
---|
| 122 | + |
---|
114 | 123 | static struct hwrng *get_current_rng(void) |
---|
115 | 124 | { |
---|
116 | 125 | struct hwrng *rng; |
---|
.. | .. |
---|
118 | 127 | if (mutex_lock_interruptible(&rng_mutex)) |
---|
119 | 128 | return ERR_PTR(-ERESTARTSYS); |
---|
120 | 129 | |
---|
121 | | - rng = current_rng; |
---|
122 | | - if (rng) |
---|
123 | | - kref_get(&rng->ref); |
---|
| 130 | + rng = get_current_rng_nolock(); |
---|
124 | 131 | |
---|
125 | 132 | mutex_unlock(&rng_mutex); |
---|
126 | 133 | return rng; |
---|
.. | .. |
---|
155 | 162 | reinit_completion(&rng->cleanup_done); |
---|
156 | 163 | |
---|
157 | 164 | skip_init: |
---|
158 | | - add_early_randomness(rng); |
---|
159 | | - |
---|
160 | 165 | current_quality = rng->quality ? : default_quality; |
---|
161 | 166 | if (current_quality > 1024) |
---|
162 | 167 | current_quality = 1024; |
---|
.. | .. |
---|
320 | 325 | const char *buf, size_t len) |
---|
321 | 326 | { |
---|
322 | 327 | int err = -ENODEV; |
---|
323 | | - struct hwrng *rng; |
---|
| 328 | + struct hwrng *rng, *old_rng, *new_rng; |
---|
324 | 329 | |
---|
325 | 330 | err = mutex_lock_interruptible(&rng_mutex); |
---|
326 | 331 | if (err) |
---|
327 | 332 | return -ERESTARTSYS; |
---|
328 | 333 | |
---|
| 334 | + old_rng = current_rng; |
---|
329 | 335 | if (sysfs_streq(buf, "")) { |
---|
330 | 336 | err = enable_best_rng(); |
---|
331 | 337 | } else { |
---|
.. | .. |
---|
337 | 343 | } |
---|
338 | 344 | } |
---|
339 | 345 | } |
---|
340 | | - |
---|
| 346 | + new_rng = get_current_rng_nolock(); |
---|
341 | 347 | mutex_unlock(&rng_mutex); |
---|
| 348 | + |
---|
| 349 | + if (new_rng) { |
---|
| 350 | + if (new_rng != old_rng) |
---|
| 351 | + add_early_randomness(new_rng); |
---|
| 352 | + put_rng(new_rng); |
---|
| 353 | + } |
---|
342 | 354 | |
---|
343 | 355 | return err ? : len; |
---|
344 | 356 | } |
---|
.. | .. |
---|
457 | 469 | int hwrng_register(struct hwrng *rng) |
---|
458 | 470 | { |
---|
459 | 471 | int err = -EINVAL; |
---|
460 | | - struct hwrng *old_rng, *tmp; |
---|
| 472 | + struct hwrng *tmp; |
---|
461 | 473 | struct list_head *rng_list_ptr; |
---|
| 474 | + bool is_new_current = false; |
---|
462 | 475 | |
---|
463 | 476 | if (!rng->name || (!rng->data_read && !rng->read)) |
---|
464 | 477 | goto out; |
---|
465 | 478 | |
---|
466 | 479 | mutex_lock(&rng_mutex); |
---|
| 480 | + |
---|
467 | 481 | /* Must not register two RNGs with the same name. */ |
---|
468 | 482 | err = -EEXIST; |
---|
469 | 483 | list_for_each_entry(tmp, &rng_list, list) { |
---|
.. | .. |
---|
482 | 496 | } |
---|
483 | 497 | list_add_tail(&rng->list, rng_list_ptr); |
---|
484 | 498 | |
---|
485 | | - old_rng = current_rng; |
---|
486 | | - err = 0; |
---|
487 | | - if (!old_rng || |
---|
488 | | - (!cur_rng_set_by_user && rng->quality > old_rng->quality)) { |
---|
| 499 | + if (!current_rng || |
---|
| 500 | + (!cur_rng_set_by_user && rng->quality > current_rng->quality)) { |
---|
489 | 501 | /* |
---|
490 | 502 | * Set new rng as current as the new rng source |
---|
491 | 503 | * provides better entropy quality and was not |
---|
.. | .. |
---|
494 | 506 | err = set_current_rng(rng); |
---|
495 | 507 | if (err) |
---|
496 | 508 | goto out_unlock; |
---|
| 509 | + /* to use current_rng in add_early_randomness() we need |
---|
| 510 | + * to take a ref |
---|
| 511 | + */ |
---|
| 512 | + is_new_current = true; |
---|
| 513 | + kref_get(&rng->ref); |
---|
497 | 514 | } |
---|
498 | | - |
---|
499 | | - if (old_rng && !rng->init) { |
---|
| 515 | + mutex_unlock(&rng_mutex); |
---|
| 516 | + if (is_new_current || !rng->init) { |
---|
500 | 517 | /* |
---|
501 | 518 | * Use a new device's input to add some randomness to |
---|
502 | 519 | * the system. If this rng device isn't going to be |
---|
503 | 520 | * used right away, its init function hasn't been |
---|
504 | | - * called yet; so only use the randomness from devices |
---|
505 | | - * that don't need an init callback. |
---|
| 521 | + * called yet by set_current_rng(); so only use the |
---|
| 522 | + * randomness from devices that don't need an init callback |
---|
506 | 523 | */ |
---|
507 | 524 | add_early_randomness(rng); |
---|
508 | 525 | } |
---|
509 | | - |
---|
| 526 | + if (is_new_current) |
---|
| 527 | + put_rng(rng); |
---|
| 528 | + return 0; |
---|
510 | 529 | out_unlock: |
---|
511 | 530 | mutex_unlock(&rng_mutex); |
---|
512 | 531 | out: |
---|
.. | .. |
---|
516 | 535 | |
---|
517 | 536 | void hwrng_unregister(struct hwrng *rng) |
---|
518 | 537 | { |
---|
| 538 | + struct hwrng *old_rng, *new_rng; |
---|
519 | 539 | int err; |
---|
520 | 540 | |
---|
521 | 541 | mutex_lock(&rng_mutex); |
---|
522 | 542 | |
---|
| 543 | + old_rng = current_rng; |
---|
523 | 544 | list_del(&rng->list); |
---|
524 | 545 | if (current_rng == rng) { |
---|
525 | 546 | err = enable_best_rng(); |
---|
.. | .. |
---|
529 | 550 | } |
---|
530 | 551 | } |
---|
531 | 552 | |
---|
| 553 | + new_rng = get_current_rng_nolock(); |
---|
532 | 554 | if (list_empty(&rng_list)) { |
---|
533 | 555 | mutex_unlock(&rng_mutex); |
---|
534 | 556 | if (hwrng_fill) |
---|
535 | 557 | kthread_stop(hwrng_fill); |
---|
536 | 558 | } else |
---|
537 | 559 | mutex_unlock(&rng_mutex); |
---|
| 560 | + |
---|
| 561 | + if (new_rng) { |
---|
| 562 | + if (old_rng != new_rng) |
---|
| 563 | + add_early_randomness(new_rng); |
---|
| 564 | + put_rng(new_rng); |
---|
| 565 | + } |
---|
538 | 566 | |
---|
539 | 567 | wait_for_completion(&rng->cleanup_done); |
---|
540 | 568 | } |
---|
.. | .. |
---|
584 | 612 | |
---|
585 | 613 | static int __init hwrng_modinit(void) |
---|
586 | 614 | { |
---|
587 | | - int ret = -ENOMEM; |
---|
| 615 | + int ret; |
---|
588 | 616 | |
---|
589 | 617 | /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */ |
---|
590 | 618 | rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL); |
---|
.. | .. |
---|
617 | 645 | unregister_miscdev(); |
---|
618 | 646 | } |
---|
619 | 647 | |
---|
620 | | -#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT |
---|
621 | | -rootfs_initcall(hwrng_modinit); |
---|
622 | | -#else |
---|
623 | 648 | module_init(hwrng_modinit); |
---|
624 | | -#endif |
---|
625 | 649 | module_exit(hwrng_modexit); |
---|
626 | 650 | |
---|
627 | 651 | MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver"); |
---|