Skip to content

Commit 253d319

Browse files
mrutland-armtytso
authored andcommitted
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 <[email protected]> Cc: Mark Brown <[email protected]> Cc: Theodore Ts'o <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 5cbe0f1 commit 253d319

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

drivers/char/random.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,24 @@ static bool crng_init_try_arch(struct crng_state *crng)
799799
return arch_init;
800800
}
801801

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+
802820
static void crng_initialize_secondary(struct crng_state *crng)
803821
{
804822
memcpy(&crng->state[0], "expand 32-byte k", 16);
@@ -811,7 +829,7 @@ static void __init crng_initialize_primary(struct crng_state *crng)
811829
{
812830
memcpy(&crng->state[0], "expand 32-byte k", 16);
813831
_extract_entropy(&input_pool, &crng->state[4], sizeof(__u32) * 12, 0);
814-
if (crng_init_try_arch(crng) && trust_cpu) {
832+
if (crng_init_try_arch_early(crng) && trust_cpu) {
815833
invalidate_batched_entropy();
816834
numa_crng_init();
817835
crng_init = 2;

include/linux/random.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#ifndef _LINUX_RANDOM_H
88
#define _LINUX_RANDOM_H
99

10+
#include <linux/bug.h>
11+
#include <linux/kernel.h>
1012
#include <linux/list.h>
1113
#include <linux/once.h>
1214

@@ -185,6 +187,26 @@ static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
185187
}
186188
#endif
187189

190+
/*
191+
* Called from the boot CPU during startup; not valid to call once
192+
* secondary CPUs are up and preemption is possible.
193+
*/
194+
#ifndef arch_get_random_seed_long_early
195+
static inline bool __init arch_get_random_seed_long_early(unsigned long *v)
196+
{
197+
WARN_ON(system_state != SYSTEM_BOOTING);
198+
return arch_get_random_seed_long(v);
199+
}
200+
#endif
201+
202+
#ifndef arch_get_random_long_early
203+
static inline bool __init arch_get_random_long_early(unsigned long *v)
204+
{
205+
WARN_ON(system_state != SYSTEM_BOOTING);
206+
return arch_get_random_long(v);
207+
}
208+
#endif
209+
188210
/* Pseudo random number generator from numerical recipes. */
189211
static inline u32 next_pseudo_random32(u32 seed)
190212
{

0 commit comments

Comments
 (0)