Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

random: add arch_get_random_*long_early()

Some architectures (e.g. arm64) can have heterogeneous CPUs, and the
boot CPU may be able to provide entropy while secondary CPUs cannot. On
such systems, arch_get_random_long() and arch_get_random_seed_long()
will fail unless support for RNG instructions has been detected on all
CPUs. This prevents the boot CPU from being able to provide
(potentially) trusted entropy when seeding the primary CRNG.

To make it possible to seed the primary CRNG from the boot CPU without
adversely affecting the runtime versions of arch_get_random_long() and
arch_get_random_seed_long(), this patch adds new early versions of the
functions used when initializing the primary CRNG.

Default implementations are provided atop of the existing
arch_get_random_long() and arch_get_random_seed_long() so that only
architectures with such constraints need to provide the new helpers.

There should be no functional change as a result of this patch.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Theodore Ts'o <tytso@mit.edu>
Link: https://lore.kernel.org/r/20200210130015.17664-3-mark.rutland@arm.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>

authored by

Mark Rutland and committed by
Theodore Ts'o
253d3194 5cbe0f13

+41 -1
+19 -1
drivers/char/random.c
··· 799 799 return arch_init; 800 800 } 801 801 802 + static bool __init crng_init_try_arch_early(struct crng_state *crng) 803 + { 804 + int i; 805 + bool arch_init = true; 806 + unsigned long rv; 807 + 808 + for (i = 4; i < 16; i++) { 809 + if (!arch_get_random_seed_long_early(&rv) && 810 + !arch_get_random_long_early(&rv)) { 811 + rv = random_get_entropy(); 812 + arch_init = false; 813 + } 814 + crng->state[i] ^= rv; 815 + } 816 + 817 + return arch_init; 818 + } 819 + 802 820 static void crng_initialize_secondary(struct crng_state *crng) 803 821 { 804 822 memcpy(&crng->state[0], "expand 32-byte k", 16); ··· 829 811 { 830 812 memcpy(&crng->state[0], "expand 32-byte k", 16); 831 813 _extract_entropy(&input_pool, &crng->state[4], sizeof(__u32) * 12, 0); 832 - if (crng_init_try_arch(crng) && trust_cpu) { 814 + if (crng_init_try_arch_early(crng) && trust_cpu) { 833 815 invalidate_batched_entropy(); 834 816 numa_crng_init(); 835 817 crng_init = 2;
+22
include/linux/random.h
··· 7 7 #ifndef _LINUX_RANDOM_H 8 8 #define _LINUX_RANDOM_H 9 9 10 + #include <linux/bug.h> 11 + #include <linux/kernel.h> 10 12 #include <linux/list.h> 11 13 #include <linux/once.h> 12 14 ··· 184 182 static inline bool __must_check arch_get_random_seed_int(unsigned int *v) 185 183 { 186 184 return false; 185 + } 186 + #endif 187 + 188 + /* 189 + * Called from the boot CPU during startup; not valid to call once 190 + * secondary CPUs are up and preemption is possible. 191 + */ 192 + #ifndef arch_get_random_seed_long_early 193 + static inline bool __init arch_get_random_seed_long_early(unsigned long *v) 194 + { 195 + WARN_ON(system_state != SYSTEM_BOOTING); 196 + return arch_get_random_seed_long(v); 197 + } 198 + #endif 199 + 200 + #ifndef arch_get_random_long_early 201 + static inline bool __init arch_get_random_long_early(unsigned long *v) 202 + { 203 + WARN_ON(system_state != SYSTEM_BOOTING); 204 + return arch_get_random_long(v); 187 205 } 188 206 #endif 189 207