From f64461291d0fd75d3fdcc9abc268447a15334ab4 Mon Sep 17 00:00:00 2001 From: Xingjun Liu Date: Mon, 24 Jun 2019 16:12:52 +0800 Subject: [PATCH 0064/2944] alinux: random: introduce the initialization seed Add random entropy with the module parameter as the initialization seed when the kernel startup. For guest OS working in VM, the random entropy will be less, it cause the random module to initialize very slowly, and if the application which running in guest os gets a certain amount of random numbers in the initialization phase, it will be blocked. This patch allows the VMM to provide a certain amount of random seed when starting guest OS, speeding up the initialization of the entire guest OS random module. Before optimization: [ 22.180236] random: crng init done After optimization: [ 1.553362] random: crng init done Signed-off-by: Xingjun Liu Reviewed-by: Liu Jiang Reviewed-by: Caspar Zhang Reviewed-by: Jia Zhang Reviewed-by: Yang Shi Reviewed-by: Liu Bo --- drivers/char/random.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/drivers/char/random.c b/drivers/char/random.c index 578d59d..9add8f4 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -287,6 +287,7 @@ #define OUTPUT_POOL_WORDS (1 << (OUTPUT_POOL_SHIFT-5)) #define SEC_XFER_SIZE 512 #define EXTRACT_SIZE 10 +#define INIT_SEED_MAX_SIZE 32 #define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long)) @@ -445,9 +446,13 @@ static void _crng_backtrack_protect(struct crng_state *crng, RATELIMIT_STATE_INIT("warn_urandom_randomness", HZ, 3); static int ratelimit_disable __read_mostly; +static char *init_seed = ""; +static bool seed_inited; module_param_named(ratelimit_disable, ratelimit_disable, int, 0644); MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression"); +module_param(init_seed, charp, 0400); +MODULE_PARM_DESC(init_seed, "Initialization random seed"); /********************************************************************** * @@ -1194,6 +1199,36 @@ void add_input_randomness(unsigned int type, unsigned int code, } EXPORT_SYMBOL_GPL(add_input_randomness); +static void add_init_randomness(const char *buffer, size_t count) +{ + struct entropy_store *poolp = &input_pool; + + mix_pool_bytes(poolp, buffer, count); + credit_entropy_bits(poolp, count * 8); +} + +static size_t ascii_hex2bin(const char *buffer, size_t count, + char *bin_buf, size_t len) +{ + const char *pbuf = buffer; + size_t bin_cnt; + char buf[4]; + int i; + + if (count == 0) + return 0; + + bin_cnt = min(len, count / 2); + buf[2] = buf[3] = 0; + for (i = 0; i < bin_cnt; i++) { + buf[0] = *pbuf++; + buf[1] = *pbuf++; + if (kstrtou8(buf, 16, &bin_buf[i]) != 0) + return 0; + } + return bin_cnt; +} + static DEFINE_PER_CPU(struct fast_pool, irq_randomness); #ifdef ADD_INTERRUPT_BENCH @@ -1243,6 +1278,8 @@ void add_interrupt_randomness(int irq, int irq_flags) __u64 ip; unsigned long seed; int credit = 0; + size_t seedlen; + char seed_bin[INIT_SEED_MAX_SIZE]; if (cycles == 0) cycles = get_reg(fast_pool, regs); @@ -1272,6 +1309,15 @@ void add_interrupt_randomness(int irq, int irq_flags) !time_after(now, fast_pool->last + HZ)) return; + if (!seed_inited) { + seed_inited = 1; + seedlen = strlen(init_seed); + seedlen = ascii_hex2bin(init_seed, seedlen, + seed_bin, sizeof(seed_bin)); + if (seedlen != 0) + add_init_randomness(seed_bin, seedlen); + } + r = &input_pool; if (!spin_trylock(&r->lock)) return; -- 1.8.3.1