diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-16 00:16:02 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-16 00:16:02 -0400 |
| commit | 99a2c789ddeb703cf7b0a3d889ab1a25cf4cbbaf (patch) | |
| tree | 3a653ba4bfb2db0c8fc52fbb5a2f0dc2e817e513 | |
| parent | fa3b39cdafbfd5d9b1d064f5cf63cf0314f1d070 (diff) | |
| parent | 9a47249d444d344051c7c0e909fad0e88515a5c2 (diff) | |
Merge tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random
Pull random updates from Ted Ts'o:
"Some changes to trust cpu-based hwrng (such as RDRAND) for
initializing hashed pointers and (optionally, controlled by a config
option) to initialize the CRNG to avoid boot hangs"
* tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random:
random: Make crng state queryable
random: remove preempt disabled region
random: add a config option to trust the CPU's hwrng
vsprintf: Add command line option debug_boot_weak_hash
vsprintf: Use hw RNG for ptr_key
random: Return nbytes filled from hw RNG
random: Fix whitespace pre random-bytes work
| -rw-r--r-- | Documentation/admin-guide/kernel-parameters.txt | 8 | ||||
| -rw-r--r-- | drivers/char/Kconfig | 14 | ||||
| -rw-r--r-- | drivers/char/random.c | 49 | ||||
| -rw-r--r-- | include/linux/random.h | 3 | ||||
| -rw-r--r-- | lib/vsprintf.c | 27 |
5 files changed, 85 insertions, 16 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index a32f2a126791..0c883029881a 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt | |||
| @@ -748,6 +748,14 @@ | |||
| 748 | 748 | ||
| 749 | debug [KNL] Enable kernel debugging (events log level). | 749 | debug [KNL] Enable kernel debugging (events log level). |
| 750 | 750 | ||
| 751 | debug_boot_weak_hash | ||
| 752 | [KNL] Enable printing [hashed] pointers early in the | ||
| 753 | boot sequence. If enabled, we use a weak hash instead | ||
| 754 | of siphash to hash pointers. Use this option if you are | ||
| 755 | seeing instances of '(___ptrval___)') and need to see a | ||
| 756 | value (hashed pointer) instead. Cryptographically | ||
| 757 | insecure, please do not use on production kernels. | ||
| 758 | |||
| 751 | debug_locks_verbose= | 759 | debug_locks_verbose= |
| 752 | [KNL] verbose self-tests | 760 | [KNL] verbose self-tests |
| 753 | Format=<0|1> | 761 | Format=<0|1> |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 212f447938ae..ce277ee0a28a 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
| @@ -554,3 +554,17 @@ config ADI | |||
| 554 | 554 | ||
| 555 | endmenu | 555 | endmenu |
| 556 | 556 | ||
| 557 | config RANDOM_TRUST_CPU | ||
| 558 | bool "Trust the CPU manufacturer to initialize Linux's CRNG" | ||
| 559 | depends on X86 || S390 || PPC | ||
| 560 | default n | ||
| 561 | help | ||
| 562 | Assume that CPU manufacturer (e.g., Intel or AMD for RDSEED or | ||
| 563 | RDRAND, IBM for the S390 and Power PC architectures) is trustworthy | ||
| 564 | for the purposes of initializing Linux's CRNG. Since this is not | ||
| 565 | something that can be independently audited, this amounts to trusting | ||
| 566 | that CPU manufacturer (perhaps with the insistence or mandate | ||
| 567 | of a Nation State's intelligence or law enforcement agencies) | ||
| 568 | has not installed a hidden back door to compromise the CPU's | ||
| 569 | random number generation facilities. | ||
| 570 | |||
diff --git a/drivers/char/random.c b/drivers/char/random.c index bd449ad52442..bf5f99fc36f1 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
| @@ -782,6 +782,7 @@ static void invalidate_batched_entropy(void); | |||
| 782 | static void crng_initialize(struct crng_state *crng) | 782 | static void crng_initialize(struct crng_state *crng) |
| 783 | { | 783 | { |
| 784 | int i; | 784 | int i; |
| 785 | int arch_init = 1; | ||
| 785 | unsigned long rv; | 786 | unsigned long rv; |
| 786 | 787 | ||
| 787 | memcpy(&crng->state[0], "expand 32-byte k", 16); | 788 | memcpy(&crng->state[0], "expand 32-byte k", 16); |
| @@ -792,10 +793,18 @@ static void crng_initialize(struct crng_state *crng) | |||
| 792 | _get_random_bytes(&crng->state[4], sizeof(__u32) * 12); | 793 | _get_random_bytes(&crng->state[4], sizeof(__u32) * 12); |
| 793 | for (i = 4; i < 16; i++) { | 794 | for (i = 4; i < 16; i++) { |
| 794 | if (!arch_get_random_seed_long(&rv) && | 795 | if (!arch_get_random_seed_long(&rv) && |
| 795 | !arch_get_random_long(&rv)) | 796 | !arch_get_random_long(&rv)) { |
| 796 | rv = random_get_entropy(); | 797 | rv = random_get_entropy(); |
| 798 | arch_init = 0; | ||
| 799 | } | ||
| 797 | crng->state[i] ^= rv; | 800 | crng->state[i] ^= rv; |
| 798 | } | 801 | } |
| 802 | #ifdef CONFIG_RANDOM_TRUST_CPU | ||
| 803 | if (arch_init) { | ||
| 804 | crng_init = 2; | ||
| 805 | pr_notice("random: crng done (trusting CPU's manufacturer)\n"); | ||
| 806 | } | ||
| 807 | #endif | ||
| 799 | crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; | 808 | crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; |
| 800 | } | 809 | } |
| 801 | 810 | ||
| @@ -1122,8 +1131,6 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) | |||
| 1122 | } sample; | 1131 | } sample; |
| 1123 | long delta, delta2, delta3; | 1132 | long delta, delta2, delta3; |
| 1124 | 1133 | ||
| 1125 | preempt_disable(); | ||
| 1126 | |||
| 1127 | sample.jiffies = jiffies; | 1134 | sample.jiffies = jiffies; |
| 1128 | sample.cycles = random_get_entropy(); | 1135 | sample.cycles = random_get_entropy(); |
| 1129 | sample.num = num; | 1136 | sample.num = num; |
| @@ -1161,8 +1168,6 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) | |||
| 1161 | * and limit entropy entimate to 12 bits. | 1168 | * and limit entropy entimate to 12 bits. |
| 1162 | */ | 1169 | */ |
| 1163 | credit_entropy_bits(r, min_t(int, fls(delta>>1), 11)); | 1170 | credit_entropy_bits(r, min_t(int, fls(delta>>1), 11)); |
| 1164 | |||
| 1165 | preempt_enable(); | ||
| 1166 | } | 1171 | } |
| 1167 | 1172 | ||
| 1168 | void add_input_randomness(unsigned int type, unsigned int code, | 1173 | void add_input_randomness(unsigned int type, unsigned int code, |
| @@ -1659,6 +1664,21 @@ int wait_for_random_bytes(void) | |||
| 1659 | EXPORT_SYMBOL(wait_for_random_bytes); | 1664 | EXPORT_SYMBOL(wait_for_random_bytes); |
| 1660 | 1665 | ||
| 1661 | /* | 1666 | /* |
| 1667 | * Returns whether or not the urandom pool has been seeded and thus guaranteed | ||
| 1668 | * to supply cryptographically secure random numbers. This applies to: the | ||
| 1669 | * /dev/urandom device, the get_random_bytes function, and the get_random_{u32, | ||
| 1670 | * ,u64,int,long} family of functions. | ||
| 1671 | * | ||
| 1672 | * Returns: true if the urandom pool has been seeded. | ||
| 1673 | * false if the urandom pool has not been seeded. | ||
| 1674 | */ | ||
| 1675 | bool rng_is_initialized(void) | ||
| 1676 | { | ||
| 1677 | return crng_ready(); | ||
| 1678 | } | ||
| 1679 | EXPORT_SYMBOL(rng_is_initialized); | ||
| 1680 | |||
| 1681 | /* | ||
| 1662 | * Add a callback function that will be invoked when the nonblocking | 1682 | * Add a callback function that will be invoked when the nonblocking |
| 1663 | * pool is initialised. | 1683 | * pool is initialised. |
| 1664 | * | 1684 | * |
| @@ -1725,30 +1745,31 @@ EXPORT_SYMBOL(del_random_ready_callback); | |||
| 1725 | * key known by the NSA). So it's useful if we need the speed, but | 1745 | * key known by the NSA). So it's useful if we need the speed, but |
| 1726 | * only if we're willing to trust the hardware manufacturer not to | 1746 | * only if we're willing to trust the hardware manufacturer not to |
| 1727 | * have put in a back door. | 1747 | * have put in a back door. |
| 1748 | * | ||
| 1749 | * Return number of bytes filled in. | ||
| 1728 | */ | 1750 | */ |
| 1729 | void get_random_bytes_arch(void *buf, int nbytes) | 1751 | int __must_check get_random_bytes_arch(void *buf, int nbytes) |
| 1730 | { | 1752 | { |
| 1753 | int left = nbytes; | ||
| 1731 | char *p = buf; | 1754 | char *p = buf; |
| 1732 | 1755 | ||
| 1733 | trace_get_random_bytes_arch(nbytes, _RET_IP_); | 1756 | trace_get_random_bytes_arch(left, _RET_IP_); |
| 1734 | while (nbytes) { | 1757 | while (left) { |
| 1735 | unsigned long v; | 1758 | unsigned long v; |
| 1736 | int chunk = min(nbytes, (int)sizeof(unsigned long)); | 1759 | int chunk = min_t(int, left, sizeof(unsigned long)); |
| 1737 | 1760 | ||
| 1738 | if (!arch_get_random_long(&v)) | 1761 | if (!arch_get_random_long(&v)) |
| 1739 | break; | 1762 | break; |
| 1740 | 1763 | ||
| 1741 | memcpy(p, &v, chunk); | 1764 | memcpy(p, &v, chunk); |
| 1742 | p += chunk; | 1765 | p += chunk; |
| 1743 | nbytes -= chunk; | 1766 | left -= chunk; |
| 1744 | } | 1767 | } |
| 1745 | 1768 | ||
| 1746 | if (nbytes) | 1769 | return nbytes - left; |
| 1747 | get_random_bytes(p, nbytes); | ||
| 1748 | } | 1770 | } |
| 1749 | EXPORT_SYMBOL(get_random_bytes_arch); | 1771 | EXPORT_SYMBOL(get_random_bytes_arch); |
| 1750 | 1772 | ||
| 1751 | |||
| 1752 | /* | 1773 | /* |
| 1753 | * init_std_data - initialize pool with system data | 1774 | * init_std_data - initialize pool with system data |
| 1754 | * | 1775 | * |
diff --git a/include/linux/random.h b/include/linux/random.h index 2ddf13b4281e..445a0ea4ff49 100644 --- a/include/linux/random.h +++ b/include/linux/random.h | |||
| @@ -36,9 +36,10 @@ extern void add_interrupt_randomness(int irq, int irq_flags) __latent_entropy; | |||
| 36 | 36 | ||
| 37 | extern void get_random_bytes(void *buf, int nbytes); | 37 | extern void get_random_bytes(void *buf, int nbytes); |
| 38 | extern int wait_for_random_bytes(void); | 38 | extern int wait_for_random_bytes(void); |
| 39 | extern bool rng_is_initialized(void); | ||
| 39 | extern int add_random_ready_callback(struct random_ready_callback *rdy); | 40 | extern int add_random_ready_callback(struct random_ready_callback *rdy); |
| 40 | extern void del_random_ready_callback(struct random_ready_callback *rdy); | 41 | extern void del_random_ready_callback(struct random_ready_callback *rdy); |
| 41 | extern void get_random_bytes_arch(void *buf, int nbytes); | 42 | extern int __must_check get_random_bytes_arch(void *buf, int nbytes); |
| 42 | 43 | ||
| 43 | #ifndef MODULE | 44 | #ifndef MODULE |
| 44 | extern const struct file_operations random_fops, urandom_fops; | 45 | extern const struct file_operations random_fops, urandom_fops; |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index cda186230287..d5b3a3f95c01 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
| @@ -1651,6 +1651,17 @@ char *device_node_string(char *buf, char *end, struct device_node *dn, | |||
| 1651 | return widen_string(buf, buf - buf_start, end, spec); | 1651 | return widen_string(buf, buf - buf_start, end, spec); |
| 1652 | } | 1652 | } |
| 1653 | 1653 | ||
| 1654 | /* Make pointers available for printing early in the boot sequence. */ | ||
| 1655 | static int debug_boot_weak_hash __ro_after_init; | ||
| 1656 | |||
| 1657 | static int __init debug_boot_weak_hash_enable(char *str) | ||
| 1658 | { | ||
| 1659 | debug_boot_weak_hash = 1; | ||
| 1660 | pr_info("debug_boot_weak_hash enabled\n"); | ||
| 1661 | return 0; | ||
| 1662 | } | ||
| 1663 | early_param("debug_boot_weak_hash", debug_boot_weak_hash_enable); | ||
| 1664 | |||
| 1654 | static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key); | 1665 | static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key); |
| 1655 | static siphash_key_t ptr_key __read_mostly; | 1666 | static siphash_key_t ptr_key __read_mostly; |
| 1656 | 1667 | ||
| @@ -1675,8 +1686,16 @@ static struct random_ready_callback random_ready = { | |||
| 1675 | 1686 | ||
| 1676 | static int __init initialize_ptr_random(void) | 1687 | static int __init initialize_ptr_random(void) |
| 1677 | { | 1688 | { |
| 1678 | int ret = add_random_ready_callback(&random_ready); | 1689 | int key_size = sizeof(ptr_key); |
| 1690 | int ret; | ||
| 1679 | 1691 | ||
| 1692 | /* Use hw RNG if available. */ | ||
| 1693 | if (get_random_bytes_arch(&ptr_key, key_size) == key_size) { | ||
| 1694 | static_branch_disable(¬_filled_random_ptr_key); | ||
| 1695 | return 0; | ||
| 1696 | } | ||
| 1697 | |||
| 1698 | ret = add_random_ready_callback(&random_ready); | ||
| 1680 | if (!ret) { | 1699 | if (!ret) { |
| 1681 | return 0; | 1700 | return 0; |
| 1682 | } else if (ret == -EALREADY) { | 1701 | } else if (ret == -EALREADY) { |
| @@ -1695,6 +1714,12 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) | |||
| 1695 | const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)"; | 1714 | const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)"; |
| 1696 | unsigned long hashval; | 1715 | unsigned long hashval; |
| 1697 | 1716 | ||
| 1717 | /* When debugging early boot use non-cryptographically secure hash. */ | ||
| 1718 | if (unlikely(debug_boot_weak_hash)) { | ||
| 1719 | hashval = hash_long((unsigned long)ptr, 32); | ||
| 1720 | return pointer_string(buf, end, (const void *)hashval, spec); | ||
| 1721 | } | ||
| 1722 | |||
| 1698 | if (static_branch_unlikely(¬_filled_random_ptr_key)) { | 1723 | if (static_branch_unlikely(¬_filled_random_ptr_key)) { |
| 1699 | spec.field_width = 2 * sizeof(ptr); | 1724 | spec.field_width = 2 * sizeof(ptr); |
| 1700 | /* string length must be less than default_width */ | 1725 | /* string length must be less than default_width */ |
