]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
random: add arch_get_random_*long_early()
authorMark Rutland <mark.rutland@arm.com>
Mon, 10 Feb 2020 13:00:13 +0000 (13:00 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 25 Jun 2022 09:46:29 +0000 (11:46 +0200)
commit 253d3194c2b58152fe830fd27c2fd83ebc6fe5ee upstream.

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>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/char/random.c
include/linux/random.h

index 97221e8b7f196792521f9ad3ec339bcf772f7f75..803fec31753a2f54f38f294947d59529fffa152b 100644 (file)
@@ -800,6 +800,24 @@ static bool crng_init_try_arch(struct crng_state *crng)
        return arch_init;
 }
 
+static bool __init crng_init_try_arch_early(struct crng_state *crng)
+{
+       int             i;
+       bool            arch_init = true;
+       unsigned long   rv;
+
+       for (i = 4; i < 16; i++) {
+               if (!arch_get_random_seed_long_early(&rv) &&
+                   !arch_get_random_long_early(&rv)) {
+                       rv = random_get_entropy();
+                       arch_init = false;
+               }
+               crng->state[i] ^= rv;
+       }
+
+       return arch_init;
+}
+
 static void __maybe_unused crng_initialize_secondary(struct crng_state *crng)
 {
        memcpy(&crng->state[0], "expand 32-byte k", 16);
@@ -812,7 +830,7 @@ static void __init crng_initialize_primary(struct crng_state *crng)
 {
        memcpy(&crng->state[0], "expand 32-byte k", 16);
        _extract_entropy(&input_pool, &crng->state[4], sizeof(__u32) * 12, 0);
-       if (crng_init_try_arch(crng) && trust_cpu) {
+       if (crng_init_try_arch_early(crng) && trust_cpu) {
                invalidate_batched_entropy();
                numa_crng_init();
                crng_init = 2;
index 0efabaaf1eb649d2ec19fedf9113d3eb9188b1cb..f45b8be3e3c4e0d730834f307bbc6ca597e5ddfd 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _LINUX_RANDOM_H
 #define _LINUX_RANDOM_H
 
+#include <linux/bug.h>
+#include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/once.h>
 
@@ -136,4 +138,24 @@ static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
 }
 #endif
 
+/*
+ * Called from the boot CPU during startup; not valid to call once
+ * secondary CPUs are up and preemption is possible.
+ */
+#ifndef arch_get_random_seed_long_early
+static inline bool __init arch_get_random_seed_long_early(unsigned long *v)
+{
+       WARN_ON(system_state != SYSTEM_BOOTING);
+       return arch_get_random_seed_long(v);
+}
+#endif
+
+#ifndef arch_get_random_long_early
+static inline bool __init arch_get_random_long_early(unsigned long *v)
+{
+       WARN_ON(system_state != SYSTEM_BOOTING);
+       return arch_get_random_long(v);
+}
+#endif
+
 #endif /* _LINUX_RANDOM_H */