[PATCH] random: add rng-seed= command line option
From: Mark Salyzyn
Date: Fri Feb 07 2020 - 10:08:23 EST
A followup to commit 428826f5358c922dc378830a1717b682c0823160
("fdt: add support for rng-seed") to extend what was started
with Open Firmware (OF or Device Tree) parsing, but also add
it to the command line.
If CONFIG_RANDOM_TRUST_BOOTLOADER is set, then feed the rng-seed
command line option length as added trusted entropy.
Always rrase all views of the rng-seed option, except early command
line parsing, to prevent leakage to applications or modules, to
eliminate any attack vector.
It is preferred to add rng-seed to the Device Tree, but some
platforms do not have this option, so this adds the ability to
provide some command-line-limited data to the entropy through this
alternate mechanism. Expect all 8 bits to be used, but must exclude
space to be accounted in the command line.
Signed-off-by: Mark Salyzyn <salyzyn@xxxxxxxxxxx>
Cc: linux-kernel@xxxxxxxxxxxxxxx
Cc: kernel-team@xxxxxxxxxxx
---
drivers/char/random.c | 8 +++++
include/linux/random.h | 5 +++
init/main.c | 73 +++++++++++++++++++++++++++++++++++-------
3 files changed, 74 insertions(+), 12 deletions(-)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index c7f9584de2c8b..2f386e411fb7b 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -2311,3 +2311,11 @@ void add_bootloader_randomness(const void *buf, unsigned int size)
add_device_randomness(buf, size);
}
EXPORT_SYMBOL_GPL(add_bootloader_randomness);
+
+#if defined(CONFIG_RANDOM_TRUST_BOOTLOADER)
+/* caller called add_device_randomness, but it is from a trusted source */
+void __init credit_trusted_entropy(unsigned int size)
+{
+ credit_entropy_bits(&input_pool, size * 8);
+}
+#endif
diff --git a/include/linux/random.h b/include/linux/random.h
index d319f9a1e4290..1e09eeadc613c 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -20,6 +20,11 @@ struct random_ready_callback {
extern void add_device_randomness(const void *, unsigned int);
extern void add_bootloader_randomness(const void *, unsigned int);
+#if defined(CONFIG_RANDOM_TRUST_BOOTLOADER)
+extern void __init credit_trusted_entropy(unsigned int b);
+#else
+static inline void credit_trusted_entropy(unsigned int b) {}
+#endif
#if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__)
static inline void add_latent_entropy(void)
diff --git a/init/main.c b/init/main.c
index cc0ee4873419c..ae976b2dea5dc 100644
--- a/init/main.c
+++ b/init/main.c
@@ -524,24 +524,53 @@ static inline void smp_prepare_cpus(unsigned int maxcpus) { }
* parsing is performed in place, and we should allow a component to
* store reference of name/value for future reference.
*/
+static const char rng_seed_str[] __initconst = "rng-seed=";
+/* try to clear rng-seed so it won't be found by user applications. */
+static void __init copy_command_line(char *dest, char *src, size_t r)
+{
+ char *rng_seed = strnstr(src, rng_seed_str, r);
+
+ if (rng_seed) {
+ size_t l = rng_seed - src;
+ char *end;
+
+ memcpy(dest, src, l);
+ dest += l;
+ src = rng_seed + strlen(rng_seed_str);
+ r -= l + strlen(rng_seed_str);
+ end = strnchr(src, r, ' ');
+ if (end) {
+ if (l && rng_seed[-1] == ' ')
+ ++end;
+ r -= end - src;
+ src = end;
+ }
+ }
+ memcpy(dest, src, r);
+ dest[r] = '\0';
+}
+
static void __init setup_command_line(char *command_line)
{
size_t len, xlen = 0, ilen = 0;
+ static const char argsep_str[] __initconst = " -- ";
+ static const char alloc_fail_msg[] __initconst =
+ "%s: Failed to allocate %zu bytes\n";
if (extra_command_line)
xlen = strlen(extra_command_line);
if (extra_init_args)
- ilen = strlen(extra_init_args) + 4; /* for " -- " */
+ ilen = strlen(extra_init_args) + strlen(argsep_str);
- len = xlen + strlen(boot_command_line) + 1;
+ len = xlen + strnlen(boot_command_line, sizeof(boot_command_line)) + 1;
saved_command_line = memblock_alloc(len + ilen, SMP_CACHE_BYTES);
if (!saved_command_line)
- panic("%s: Failed to allocate %zu bytes\n", __func__, len + ilen);
+ panic(alloc_fail_msg, __func__, len + ilen);
static_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
if (!static_command_line)
- panic("%s: Failed to allocate %zu bytes\n", __func__, len);
+ panic(alloc_fail_msg, __func__, len);
if (xlen) {
/*
@@ -549,11 +578,14 @@ static void __init setup_command_line(char *command_line)
* lines because there could be dashes (separator of init
* command line) in the command lines.
*/
- strcpy(saved_command_line, extra_command_line);
- strcpy(static_command_line, extra_command_line);
+ copy_command_line(saved_command_line, extra_command_line, xlen);
+ copy_command_line(static_command_line, extra_command_line,
+ xlen);
}
- strcpy(saved_command_line + xlen, boot_command_line);
- strcpy(static_command_line + xlen, command_line);
+ copy_command_line(saved_command_line + xlen, boot_command_line,
+ len - xlen - 1);
+ copy_command_line(static_command_line + xlen, command_line,
+ len - xlen - 1);
if (ilen) {
/*
@@ -562,13 +594,15 @@ static void __init setup_command_line(char *command_line)
* to init.
*/
len = strlen(saved_command_line);
- if (!strstr(boot_command_line, " -- ")) {
- strcpy(saved_command_line + len, " -- ");
- len += 4;
+ if (!strnstr(boot_command_line, argsep_str,
+ sizeof(boot_command_line))) {
+ strcpy(saved_command_line + len, argsep_str);
+ len += strlen(argsep_str);
} else
saved_command_line[len++] = ' ';
- strcpy(saved_command_line + len, extra_init_args);
+ copy_command_line(saved_command_line + len, extra_init_args,
+ ilen - strlen(argsep_str));
}
}
@@ -875,6 +909,21 @@ asmlinkage __visible void __init start_kernel(void)
rand_initialize();
add_latent_entropy();
add_device_randomness(command_line, strlen(command_line));
+ if (IS_BUILTIN(CONFIG_RANDOM_TRUST_BOOTLOADER)) {
+ size_t l = strlen(command_line);
+ char *rng_seed = strnstr(command_line, rng_seed_str, l);
+
+ if (rng_seed) {
+ char *end;
+
+ rng_seed += strlen(rng_seed_str);
+ l -= rng_seed - command_line;
+ end = strnchr(rng_seed, l, ' ');
+ if (end)
+ l = end - rng_seed;
+ credit_trusted_entropy(l);
+ }
+ }
boot_init_stack_canary();
time_init();
--
2.25.0.341.g760bfbb309-goog