All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Jörn Engel" <joern@purestorage.com>
To: "Theodore Ts'o" <tytso@mit.edu>
Cc: Kees Cook <keescook@chromium.org>,
	"Jason A. Donenfeld" <Jason@zx2c4.com>,
	Michael Schmitz <schmitzmic@gmail.com>,
	Stephan Mueller <stephan.mueller@atsec.com>,
	Jason Cooper <jason@lakedaemon.net>,
	Herbert Xu <herbert@gondor.apana.org.au>,
	"H. Peter Anvin" <hpa@zytor.com>,
	Christoph Hellwig <hch@infradead.org>, Greg Price <price@mit.edu>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH] random: add regrand
Date: Fri, 10 Nov 2017 17:17:39 -0800	[thread overview]
Message-ID: <20171111011739.GI6911@cork> (raw)
In-Reply-To: <20171110213039.GA6911@cork>

Forgot to Cc: linux-kernel.

On Fri, Nov 10, 2017 at 01:30:39PM -0800, Jörn Engel wrote:
> Regrand is a replacement for drivers/char/random.c.  It is supposed to
> achieve the following design goals:
> 
> 1. /dev/random shall never block.
> 2. /dev/urandom shall never return bad randomness.
> 3. Any machine supported by Linux must have good randomness.
> 4. Any entropy source that is unavailable on some machines is useless.
> 5. By the time we start userspace, the random pool must be fully initialized.
> 6. Entropy never gets XOR'ed, always hashed.
> 7. In-kernel users never receive bad randomness.
> 
> I believe it achieves all but the last.  Sadly there are a few
> exceptions where random numbers are consumed before the entropy pool can
> be initialized.  In contrast, I believe current drivers/char/random.c
> achieves none of the above.
> 
> That is a pretty bold claim, so please try to poke holes.  For the
> moment, I think regrand should be optional and users should decide which
> random number generator they trust more.  Maybe after a year or two,
> provided noone manages to find a problem in regrand, it can be made the
> default.
> 
> Copyright for regrand proper is Public Domain.  Feel free to port the
> version in Documentation/regrand.c to any OS.  Most of the code in
> drivers/char/regrand.c is copied from either crypto/sha3_generic.c or
> drivers/char/random.c.  I didn't want to go through crypto API to access
> sha3 code and had to implement an interface compatible to the existing
> random number generator.  Regrand proper is tiny in comparison.
> 
> Happy reading.
> 
> Signed-off-by: Joern Engel <joern@purestorage.com>
> ---
>  Documentation/regrand.c               | 365 ++++++++++++++++++
>  arch/Kconfig                          |   1 +
>  arch/x86/include/asm/stackprotector.h |   2 +-
>  arch/x86/kernel/apic/apic.c           |   2 +
>  drivers/char/Kconfig                  |  11 +
>  drivers/char/Makefile                 |   7 +-
>  drivers/char/regrand.c                | 673 ++++++++++++++++++++++++++++++++++
>  include/linux/genhd.h                 |   5 +
>  include/linux/hw_random.h             |   4 +
>  include/linux/random.h                |  25 +-
>  kernel/fork.c                         |   2 +-
>  kernel/panic.c                        |   2 +-
>  mm/slab.c                             |   2 +-
>  mm/slab_common.c                      |   4 +-
>  mm/slub.c                             |   5 +-
>  15 files changed, 1093 insertions(+), 17 deletions(-)
>  create mode 100644 Documentation/regrand.c
>  create mode 100644 drivers/char/regrand.c
> 
> diff --git a/Documentation/regrand.c b/Documentation/regrand.c
> new file mode 100644
> index 000000000000..07a1b87c2bb7
> --- /dev/null
> +++ b/Documentation/regrand.c
> @@ -0,0 +1,365 @@
> +/*
> + * regrand - Random number generator using register state at time of
> + * interrupt.  Uses the same principle as Dakarand, drift between two
> + * unsynchronized high-precision timers, as entropy source.  Should
> + * work reasonably well on any CPU that can generate interrupts.
> + *
> + * Public Domain
> + */
> +#error ADD INCLUDES
> +
> +/*
> + * Based on a million boots, each interrupt seems to yield about 10-15
> + * bits of entropy.  That means 20 samples might be enough for
> + * cryptographically strong random numbers.  Naturally we want more to
> + * give us a comfortable safety margin.  128 should be good enough.
> + */
> +#define SAMPLES_NEEDED	(128)					// [2]
> +
> +#define	ACCESS_ONCE(x)		(*(volatile __typeof(x) *)&(x))
> +
> +/* 256b hash value */
> +struct half_hash {						// [1]
> +	uint64_t h[4];
> +};
> +
> +/* 512b hash value */
> +struct full_hash {						// [1]
> +	union {
> +		struct half_hash half[2];
> +		uint64_t h[8];
> +	};
> +};
> +
> +struct per_cpu_state {						// [3]
> +	struct half_hash half;	/* 256 bits of state */
> +	uint64_t p_time;	/* last time we produced entropy */
> +	uint64_t c_time;	/* last time we consumed entropy */
> +};
> +
> +static struct half_hash global_pool;				// [3]
> +static int uninitialized_count = INT_MAX;			// [8]
> +static int global_lock;						// [4]
> +
> +static struct per_cpu_state *get_local_state(void)		// [5]
> +{
> +#error FILL ME IN
> +	/*
> +	 * Should return a pointer to per-cpu state.  Most RNG
> +	 * operations are done on local state, without cacheline
> +	 * pingpong causing unnecessary slowdowns.
> +	 * Bonus points if the pointer is cacheline-aligned.  The
> +	 * structure size of 64 bytes is chosen to fit into
> +	 * 1-2 cachelines in most architectures.
> +	 */
> +}
> +
> +static uint64_t get_time(void)					// [5]
> +{
> +#error FILL ME IN
> +	/*
> +	 * Should return a time.  Doesn't need to be monotonic or
> +	 * non-wrapping, but should be scaled to increment every
> +	 * 1-10ms or so.  We will sample entropy on every increment,
> +	 * so higher precision means more entropy and more overhead,
> +	 * lower precision means less entropy and less overhead.
> +	 */
> +}
> +
> +static struct full_hash hash512(void *p1, int n1, void *p2, int n2)	// [5]
> +{
> +#error FILL ME IN
> +	/*
> +	 * Calculate a 512bit hash from both inputs.  Second input may
> +	 * be empty.  I'd suggest 512bit sha2 or sha3.
> +	 */
> +}
> +
> +static void wait_a_while(void)					// [5]
> +{
> +#error FILL ME IN
> +	/*
> +	 * Some delay function - only used when asking for random
> +	 * numbers before the pool has initialized.  Feel free to do
> +	 * something fancy like completions if you don't want a
> +	 * spinning loop.
> +	 */
> +}
> +
> +#if 0 /* enable to estimate boottime entropy */
> +static uint32_t boot_log[SAMPLES_NEEDED][3];			// [6]
> +static uint32_t tsc0;
> +
> +static void log_boot_entropy(struct pt_regs *regs, uint64_t cascade_hash)
> +{
> +	struct full_hash hash;
> +	int i, slot = SAMPLES_NEEDED - uninitialized_count;
> +
> +	if ((unsigned)slot > SAMPLES_NEEDED)
> +		return;
> +	if (slot == 0)
> +		tsc0 = rdtsc();
> +	hash = hash512(regs, sizeof(struct pt_regs), NULL, 0);
> +	boot_log[slot][0] = hash.h[0];
> +	boot_log[slot][1] = cascade_hash;
> +	boot_log[slot][2] = rdtsc() - tsc0;
> +	if (uninitialized_count == 1) {
> +		for (i = 0; i < SAMPLES_NEEDED; i++) {
> +			pr_info("boot_entropy %03d: %08x %08x %08x\n", i, boot_log[i][0], boot_log[i][1], boot_log[i][2]);
> +		}
> +	}
> +}
> +#else
> +static inline void log_boot_entropy(struct pt_regs *regs, uint64_t cascade_hash) {}
> +#endif
> +
> +static void produce_entropy_from_irq_regs(void *regs, int n)	// [7]
> +{
> +#error HOOK ME UP
> +	/*
> +	 * Should be called on every interrupt.  Arguments should be
> +	 * start and size of saved register state at the time of
> +	 * interrupt.
> +	 */
> +	struct per_cpu_state *state = get_local_state();
> +	uint64_t time = get_time();
> +	struct full_hash hash;
> +
> +	/* Ratelimit to reduce interrupt overhead */
> +	if (state->p_time == time && !uninitialized_count)
> +		return;
> +	state->p_time = time;
> +
> +	/* Mix local state and new entropy from registers */
> +	hash = hash512(state, sizeof(state->half), regs, sizeof(struct pt_regs));
> +	state->half = hash.half[0];
> +
> +	/* Only mix with global state, if uncontended */
> +	if (!trylock(&global_lock))
> +		return;
> +
> +	/* Mix local and global state.  */
> +	hash = hash512(&global_pool, sizeof(global_pool), &hash, sizeof(hash));
> +	state->half = hash.half[0];
> +	global_pool = hash.half[1];
> +
> +	if (uninitialized_count) {
> +		log_boot_entropy(regs, hash.h[0]);
> +		uninitialized_count--;
> +	}
> +	unlock(&global_lock);
> +}
> +
> +static void regrand_init(void)					// [8]
> +{
> +#error HOOK ME UP
> +	struct full_hash hash;
> +
> +	/* Interrupts before this loop may be synchronized */
> +	uninitialized_count = SAMPLES_NEEDED;
> +	/* without volatile, gcc will turn this into while (1) */
> +	while (ACCESS_ONCE(uninitialized_count)) {
> +		hash = hash512(&hash, sizeof(hash), NULL, 0);
> +	}
> +}
> +
> +/*
> + * Returns 32 likely-random bytes.  No guarantees, as we don't wait
> + * for enough entropy to accumulate.  Use only if you need semi-good
> + * entropy early in boot before RNG initialization can happen.
> + */
> +static struct half_hash consume_entropy_unsafe(void)		// [9]
> +{
> +#error HOOK ME UP
> +	struct per_cpu_state *state = get_local_state();
> +	uint64_t time = get_time();
> +	struct full_hash hash;
> +
> +	if (state->c_time != time || uninitialized_count) {
> +		state->c_time = time;
> +		/* Mix global pool into local pool, no locking */
> +		hash = hash512(&global_pool, sizeof(global_pool), &state->half, sizeof(state->half));
> +	} else {
> +		/* Only use local pool, reducing contention and overhead */
> +		hash = hash512(&state->half, sizeof(state->half), NULL, 0);
> +	}
> +	state->half = hash.half[0];
> +	return hash.half[1];
> +}
> +
> +/* Returns 32 random bytes */
> +struct half_hash consume_entropy(void)				// [10]
> +{
> +#error HOOK ME UP
> +	while (uninitialized_count)
> +		wait_a_while();
> +	return consume_entropy_unsafe();
> +}
> +
> +/*
> + * Design goals:
> + * -------------
> + * 1. /dev/random shall never block.
> + * 2. /dev/urandom shall never return bad randomness.
> + *
> + * That's it, really.  Everything else is a corrolary.
> + *
> + * 3. Any machine supported by Linux must have good randomness.
> + * 4. Any entropy source that is unavailable on some machines is useless.
> + * 5. By the time we start userspace, the random pool must be fully initialized.
> + * 6. Entropy never gets XOR'ed, always hashed.
> + * 7. In-kernel users never receive bad randomness.
> + *
> + * The existing Linux kernel RNG (drivers/char/random) fails those goals.  I
> + * personally find it so bad that it was better to restart from scratch than to
> + * try and salvage anything from it.
> + *
> + *
> + * Design principle:
> + * -----------------
> + * Regrand is basically dakarand, Dan Kaminsky famous 4-line javascript RNG:
> + * function millis()         { return Date.now(); }
> + * function flip_coin()      { n=0; then = millis()+1; while(millis()<=then) { n=!n; } return n; }
> + * function get_fair_bit()   { while(1) { a=flip_coin(); if(a!=flip_coin()) { return(a); } } }
> + * function get_random_byte(){ n=0; bits=8; while(bits--){ n<<=1; n|=get_fair_bit(); } return n; }
> + *
> + * The principle behind both is to extract entropy from the drift between two
> + * unsynchronized high-precision clocks.  Both use CPU registers and interrupt
> + * timing as the two clocks.
> + *
> + * Regrand uses the stored registers at interrupt time and hashes the lot.  The
> + * stored registers serve as a high-resolution timer of sorts.  At least one of
> + * the registers tends to change with every clock cycle, often more than one if
> + * the CPU can exploit instruction level parallelism (IPL).
> + *
> + * Naïvely using registers during bootup tends to yield no entropy, because
> + * interrupts are disabled for much of the bootup process and tend to happen
> + * immediately after re-enabling interrupts.  That means the register state is
> + * synchronized.  To avoid this problem, regrand_init() monopolized the CPU with
> + * interrupts enabled.
> + *
> + * regrand_init() has to run some kind of loop that permutes register content.
> + * We want more than one bit of entropy per sample, so instead of dakarand's
> + * "n=!n" we calculate hashes.  That should have reasonably high IPL and improve
> + * timer resolution.  It also avoids going back to old register state in the
> + * loop.
> + *
> + *
> + * Details:
> + * --------
> + * [1] We use a 256bit half_hash and a 512bit full_hash throughout.  256bit of
> + * state are enough for a good crypto-hash based PRNG.
> + *
> + * [2] To initialize the RNG we need 128 samples.  Empirically each sample seems
> + * to contain more than 10 bits of entropy, giving us >1280 bits in total.  That
> + * is comfortably more than the 256 bits needed, giving a nice safety margin.
> + * If you are really paranoid, feel free to increase SAMPLES_NEEDED.
> + *
> + * Don't even think about decreasing SAMPLES_NEEDED.  Seriously!
> + *
> + * [3] Most operations only consider per_cpu_state.  Once per get_time()
> + * increment we mix per_cpu_state with global state, both for producers and
> + * consumers.  That way the common operations are relatively cheap and scale
> + * well.  At the same time we keep mixing new entropy into the global pool and
> + * tap into the global pool even on CPUs that don't ever see interrupts.
> + *
> + * [4] Adding entropy to the global pool is protected by a lock.  On lock
> + * contention the losing CPU simply ignores the global pool.  One update per
> + * get_time() increment is enough, there is no need to turn the global pool into
> + * a bottleneck when you have enough entropy anyway.
> + *
> + * [5] get_local_state(), get_time(), hash512() and wait_a_while() need to get
> + * implemented somehow.  Details vary between operating systems.
> + *
> + * [6] log_boot_entropy() can be used to estimate how much entropy is being
> + * gathered.  See 'entropy estimate' below.
> + *
> + * [7] produce_entropy_from_irq_regs() is the sole entropy producer.  In the
> + * common case it just returns.  Therefore it should be safe to call this
> + * function on every interrupt, even at rates of 100k interrupts per second.
> + * Once per get_time() increment it hashes registers and updates local state.
> + * If global state isn't locked, it mixes local and global state.
> + *
> + * uninitialized_count is only decremented if we can mix with the global pool.
> + * Therefore, we know the global pool has been mixed SAMPLES_NEEDED times
> + * before we consider the RNG initialized.
> + *
> + * On bootup it doesn't wait for get_time() increments and always collects
> + * entropy.
> + *
> + * Mixing is done via hash512().  Mixing via weak hash functions or by XORing
> + * new values in allows attacks where attacker-controlled data removes entropy
> + * from the pool.  Please never do such a thing.
> + *
> + * [8] regrand_init() provides a "counter loop" that is not synchronized with
> + * interrupts.  It also resets uninitialized_count.  We don't trust any samples
> + * before regrand_init() starts, so uninitialized_count is set to INT_MAX on
> + * boot.  Assuming no more than INT_MAX interrupts occur before regrand_init()
> + * is called, that's an easy way to not account the untrusted samples.
> + *
> + * [9] consume_entropy_unsafe() commonly calculates a 512bit hash from the
> + * 256bit per_cpu_state.  Half of that get returned, the other half become the
> + * new per_cpu_state.  Predicting the other half from returned values should be
> + * impossible.  If it is possible, you didn't use a good enough crypto-hash.
> + *
> + * Once per get_time() increment we hash both local and global pool.  Therefore
> + * any CPU received fresh entropy at a steady rate, even CPUs that never see
> + * interrupts.
> + *
> + * [10] consume_entropy() is the main consumer, ideally the only consumer.
> + * Calling it before RNG initialization happened results in blocking, but never
> + * returns bad random numbers.
> + *
> + * Calling it before RNG initialization can happen results in a deadlock and a
> + * machine that cannot boot.  In Linux the stack protector canary and some
> + * slab allocator debug code has such a problem.  If possible, we should
> + * reorder the code such that RNG initialization happens first.  If that is not
> + * possible, I don't have a good answer.  You can try using rdrand() or
> + * something like that, but the regular system RNG cannot give you a good random
> + * number.
> + *
> + * I really hate ever returning bad random numbers.  That almost always leads
> + * to bugs because people make assumptions that only work with good random
> + * numbers - sometimes with catastrophic consequences.  So the least we can do
> + * is make it bloody obvious that callers are doing something horrible.  Maybe
> + * consume_entropy_unsafe() should be renamed to
> + * consume_entropy_unsafe____any_callers_must_be_fully_aware_of_consequences()
> + * or something like that.
> + *
> + *
> + * Entropy estimate:
> + * ----------------
> + *
> + * I booted an allnoconfig-based kernel a million times with log_boot_entropy()
> + * enabled.  Precise command line was:
> + * taskset -c $1 chrt -r 50 timeout 1 kvm -serial file:$S -kernel bzImage -display none -append 'ro console=ttyS0,115200 console=tty0' > /dev/null 2>&1
> + * My test machine had 20 cores and I used 19 threads.  Hyperthreading was
> + * enabled, I have yet to repeat this test with hyperthreading disabled.
> + * CONFIG_HZ=1000 was chosen to minimize both boot time and entropy gathered.
> + *
> + * The most common register hashes were seen <3000 times for any one sample.
> + * That would give 8 bits of entropy for those common samples or more entropy
> + * for less common samples.  The most common register hash across all samples
> + * was see 350517 times, giving a little more than 1 bit of entropy.  The 63rd
> + * most common was seen 12208 times, the 127th most common 11110 times.  At
> + * least 94 samples should yield 6 bits of entropy or more.  Assuming we only
> + * encounter samples from the most common set and extract no entropy from the
> + * order of samples, that would still give more than 564 bits.
> + *
> + * Zstd -19 can compress the rdtsc() values to 266MB, indicating an average
> + * entropy of 266 bytes or 2128 bits.  With a delta filter I can reduce that to
> + * 1868 bits.  Delta filter and xz -9 achieves 1621 bits.  That is still 6x more
> + * than the 256 bits we need, a big enough safety margin to let me sleep at
> + * night.  Register hashes compress much worse - they probably don't contain any
> + * more entropy, but are computationally much more expensive than a simple
> + * counter.  I get 4159 bits with zstd -19.
> + *
> + * If someone with better statistical skills (or just anyone) would like to
> + * double check, I can provide the logs.  Full logs are 1.6G compressed.
> + *
> + * If someone has the resources to do large-scale boot tests on hardware, please
> + * do so.
> + *
> + * Please don't take my word and question everything I said.  The OS' random
> + * number generator is something we really want to get right.
> + */
> diff --git a/arch/Kconfig b/arch/Kconfig
> index d789a89cb32c..382c8ef44cc8 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -431,6 +431,7 @@ config GCC_PLUGIN_SANCOV
>  config GCC_PLUGIN_LATENT_ENTROPY
>  	bool "Generate some entropy during boot and runtime"
>  	depends on GCC_PLUGINS
> +	depends on !REGRAND
>  	help
>  	  By saying Y here the kernel will instrument some kernel code to
>  	  extract some entropy from both original and artificially created
> diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h
> index 8abedf1d650e..b057b49bee9b 100644
> --- a/arch/x86/include/asm/stackprotector.h
> +++ b/arch/x86/include/asm/stackprotector.h
> @@ -71,7 +71,7 @@ static __always_inline void boot_init_stack_canary(void)
>  	 * there it already has some randomness on most systems. Later
>  	 * on during the bootup the random pool has true entropy too.
>  	 */
> -	get_random_bytes(&canary, sizeof(canary));
> +	__get_random_bytes(&canary, sizeof(canary));
>  	tsc = rdtsc();
>  	canary += tsc + (tsc << 32UL);
>  	canary &= CANARY_MASK;
> diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
> index ff891772c9f8..639cdd22382a 100644
> --- a/arch/x86/kernel/apic/apic.c
> +++ b/arch/x86/kernel/apic/apic.c
> @@ -34,6 +34,7 @@
>  #include <linux/dmi.h>
>  #include <linux/smp.h>
>  #include <linux/mm.h>
> +#include <linux/random.h>
>  
>  #include <asm/trace/irq_vectors.h>
>  #include <asm/irq_remapping.h>
> @@ -1055,6 +1056,7 @@ __visible void __irq_entry smp_apic_timer_interrupt(struct pt_regs *regs)
>  	entering_ack_irq();
>  	trace_local_timer_entry(LOCAL_TIMER_VECTOR);
>  	local_apic_timer_interrupt();
> +	add_interrupt_randomness(0, 0);
>  	trace_local_timer_exit(LOCAL_TIMER_VECTOR);
>  	exiting_irq();
>  
> diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
> index 623714344600..4eb3a66786e4 100644
> --- a/drivers/char/Kconfig
> +++ b/drivers/char/Kconfig
> @@ -6,6 +6,17 @@ menu "Character devices"
>  
>  source "drivers/tty/Kconfig"
>  
> +config REGRAND
> +	bool "regrand random number generator"
> +	default n
> +	help
> +	  Say Y here if you want to use regrand random number
> +	  generator instead of the default choice.  Regrand uses a
> +	  single entropy source - the register state at the time of
> +	  interrupts.  It is likely a better choice, but relatively
> +	  new and has therefore seen less scrutiny.
> +	  When in doubt, say "N".
> +
>  config DEVMEM
>  	bool "/dev/mem virtual device support"
>  	default y
> diff --git a/drivers/char/Makefile b/drivers/char/Makefile
> index 53e33720818c..e42fc5b17eba 100644
> --- a/drivers/char/Makefile
> +++ b/drivers/char/Makefile
> @@ -2,7 +2,12 @@
>  # Makefile for the kernel character device drivers.
>  #
>  
> -obj-y				+= mem.o random.o
> +obj-y				+= mem.o
> +ifeq ($(CONFIG_REGRAND),y)
> +  obj-y				+= regrand.o
> +else
> +  obj-y				+= random.o
> +endif
>  obj-$(CONFIG_TTY_PRINTK)	+= ttyprintk.o
>  obj-y				+= misc.o
>  obj-$(CONFIG_ATARI_DSP56K)	+= dsp56k.o
> diff --git a/drivers/char/regrand.c b/drivers/char/regrand.c
> new file mode 100644
> index 000000000000..6e1b28fb4e05
> --- /dev/null
> +++ b/drivers/char/regrand.c
> @@ -0,0 +1,673 @@
> +/*
> + * regrand - Random number generator using register state at time of
> + * interrupt.  Uses the same principle as Dakarand, drift between two
> + * unsynchronized high-precision timers, as entropy source.  Should
> + * work reasonably well on any CPU that can generate interrupts.
> + *
> + * Public Domain
> + */
> +#include <linux/kernel.h>
> +#include <linux/random.h>
> +#include <linux/sched.h>
> +#include <linux/syscalls.h>
> +
> +/*
> + * Based on a million boots, each interrupt seems to yield about 10-15
> + * bits of entropy.  That means 20 samples might be enough for
> + * cryptographically strong random numbers.  Naturally we want more to
> + * give us a comfortable safety margin.  128 should be good enough.
> + */
> +#define SAMPLES_NEEDED	(128)
> +
> +/* 256b hash value */
> +struct half_hash {
> +	uint64_t h[4];
> +};
> +
> +/* 512b hash value */
> +struct full_hash {
> +	union {
> +		struct half_hash half[2];
> +		uint64_t h[8];
> +	};
> +};
> +
> +struct per_cpu_state {
> +	struct half_hash half;	/* 256 bits of state */
> +	uint64_t p_time;	/* last time we produced entropy */
> +	uint64_t c_time;	/* last time we consumed entropy */
> +};
> +
> +static DEFINE_PER_CPU(struct per_cpu_state, per_cpu_state);
> +
> +static struct half_hash global_pool;
> +static int uninitialized_count = INT_MAX;
> +static DEFINE_SPINLOCK(global_lock);
> +static DECLARE_WAIT_QUEUE_HEAD(uninitialized_wait);
> +
> +static struct per_cpu_state *get_local_state(void)
> +{
> +	/*
> +	 * Should return a pointer to per-cpu state.  Most RNG
> +	 * operations are done on local state, without cacheline
> +	 * pingpong causing unnecessary slowdowns.
> +	 * Bonus points if the pointer is cacheline-aligned.  The
> +	 * structure size of 64 bytes is chosen to perfectly fit into
> +	 * 1-2 cachelines in most architectures.
> +	 */
> +	return this_cpu_ptr(&per_cpu_state);
> +}
> +
> +static uint64_t get_time(void)
> +{
> +	/*
> +	 * Should return a time.  Doesn't need to be monotonic or
> +	 * non-wrapping, but should be scaled to increment every
> +	 * 1-10ms or so.  We will sample entropy on every increment,
> +	 * so higher precision means more entropy and more overhead,
> +	 * lower precision means less entropy and less overhead.
> +	 */
> +	return jiffies;
> +}
> +
> +/*
> + * Sha3 code copied from crypto/sha3_generic.c.  For one we cannot
> + * depend on loadable modules.  Also, the necessary boilerplate code
> + * to do error handling on functions that shouldn't return errors to
> + * begin with is about as much as a full implementation of sha3.
> + * Therefore we have yet another copy for now.
> + */
> +#define SHA3_224_DIGEST_SIZE	(224 / 8)
> +#define SHA3_224_BLOCK_SIZE	(200 - 2 * SHA3_224_DIGEST_SIZE)
> +
> +#define SHA3_256_DIGEST_SIZE	(256 / 8)
> +#define SHA3_256_BLOCK_SIZE	(200 - 2 * SHA3_256_DIGEST_SIZE)
> +
> +#define SHA3_384_DIGEST_SIZE	(384 / 8)
> +#define SHA3_384_BLOCK_SIZE	(200 - 2 * SHA3_384_DIGEST_SIZE)
> +
> +#define SHA3_512_DIGEST_SIZE	(512 / 8)
> +#define SHA3_512_BLOCK_SIZE	(200 - 2 * SHA3_512_DIGEST_SIZE)
> +
> +struct sha3_state {
> +	u64		st[25];
> +	unsigned int	md_len;
> +	unsigned int	rsiz;
> +	unsigned int	rsizw;
> +
> +	unsigned int	partial;
> +	u8		buf[SHA3_224_BLOCK_SIZE];
> +};
> +
> +#define KECCAK_ROUNDS 24
> +
> +#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
> +
> +static const u64 keccakf_rndc[24] = {
> +	0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808aULL,
> +	0x8000000080008000ULL, 0x000000000000808bULL, 0x0000000080000001ULL,
> +	0x8000000080008081ULL, 0x8000000000008009ULL, 0x000000000000008aULL,
> +	0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000aULL,
> +	0x000000008000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL,
> +	0x8000000000008003ULL, 0x8000000000008002ULL, 0x8000000000000080ULL,
> +	0x000000000000800aULL, 0x800000008000000aULL, 0x8000000080008081ULL,
> +	0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL
> +};
> +
> +static const int keccakf_rotc[24] = {
> +	1,  3,  6,  10, 15, 21, 28, 36, 45, 55, 2,  14,
> +	27, 41, 56, 8,  25, 43, 62, 18, 39, 61, 20, 44
> +};
> +
> +static const int keccakf_piln[24] = {
> +	10, 7,  11, 17, 18, 3, 5,  16, 8,  21, 24, 4,
> +	15, 23, 19, 13, 12, 2, 20, 14, 22, 9,  6,  1
> +};
> +
> +/* update the state with given number of rounds */
> +
> +static void keccakf(u64 st[25])
> +{
> +	int i, j, round;
> +	u64 t, bc[5];
> +
> +	for (round = 0; round < KECCAK_ROUNDS; round++) {
> +
> +		/* Theta */
> +		for (i = 0; i < 5; i++)
> +			bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15]
> +				^ st[i + 20];
> +
> +		for (i = 0; i < 5; i++) {
> +			t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
> +			for (j = 0; j < 25; j += 5)
> +				st[j + i] ^= t;
> +		}
> +
> +		/* Rho Pi */
> +		t = st[1];
> +		for (i = 0; i < 24; i++) {
> +			j = keccakf_piln[i];
> +			bc[0] = st[j];
> +			st[j] = ROTL64(t, keccakf_rotc[i]);
> +			t = bc[0];
> +		}
> +
> +		/* Chi */
> +		for (j = 0; j < 25; j += 5) {
> +			for (i = 0; i < 5; i++)
> +				bc[i] = st[j + i];
> +			for (i = 0; i < 5; i++)
> +				st[j + i] ^= (~bc[(i + 1) % 5]) &
> +					     bc[(i + 2) % 5];
> +		}
> +
> +		/* Iota */
> +		st[0] ^= keccakf_rndc[round];
> +	}
> +}
> +
> +static void sha3_512_init(struct sha3_state *sctx)
> +{
> +	memset(sctx, 0, sizeof(*sctx));
> +	sctx->md_len = SHA3_512_DIGEST_SIZE;
> +	sctx->rsiz = 200 - 2 * SHA3_512_DIGEST_SIZE;
> +	sctx->rsizw = sctx->rsiz / 8;
> +}
> +
> +static void sha3_update(struct sha3_state *sctx, const u8 *data, unsigned int len)
> +{
> +	unsigned int done;
> +	const u8 *src;
> +
> +	done = 0;
> +	src = data;
> +
> +	if ((sctx->partial + len) > (sctx->rsiz - 1)) {
> +		if (sctx->partial) {
> +			done = -sctx->partial;
> +			memcpy(sctx->buf + sctx->partial, data,
> +			       done + sctx->rsiz);
> +			src = sctx->buf;
> +		}
> +
> +		do {
> +			unsigned int i;
> +
> +			for (i = 0; i < sctx->rsizw; i++)
> +				sctx->st[i] ^= ((u64 *) src)[i];
> +			keccakf(sctx->st);
> +
> +			done += sctx->rsiz;
> +			src = data + done;
> +		} while (done + (sctx->rsiz - 1) < len);
> +
> +		sctx->partial = 0;
> +	}
> +	memcpy(sctx->buf + sctx->partial, src, len - done);
> +	sctx->partial += (len - done);
> +}
> +
> +static void sha3_final(struct sha3_state *sctx, void *out)
> +{
> +	unsigned int i, inlen = sctx->partial;
> +
> +	sctx->buf[inlen++] = 0x06;
> +	memset(sctx->buf + inlen, 0, sctx->rsiz - inlen);
> +	sctx->buf[sctx->rsiz - 1] |= 0x80;
> +
> +	for (i = 0; i < sctx->rsizw; i++)
> +		sctx->st[i] ^= ((u64 *) sctx->buf)[i];
> +
> +	keccakf(sctx->st);
> +
> +	for (i = 0; i < sctx->rsizw; i++)
> +		sctx->st[i] = cpu_to_le64(sctx->st[i]);
> +
> +	memcpy(out, sctx->st, sctx->md_len);
> +
> +	memset(sctx, 0, sizeof(*sctx));
> +}
> +
> +static struct full_hash hash512(void *p1, int n1, void *p2, int n2)
> +{
> +	struct sha3_state state;
> +	struct full_hash hash;
> +	/*
> +	 * Calculate a 512bit hash from both inputs.  Second input may
> +	 * be empty.
> +	 */
> +	sha3_512_init(&state);
> +	sha3_update(&state, p1, n1);
> +	if (p2)
> +		sha3_update(&state, p2, n2);
> +	sha3_final(&state, &hash);
> +	return hash;
> +}
> +
> +static void wait_a_while(void)
> +{
> +	/*
> +	 * Some delay function - only used when asking for random
> +	 * numbers before the pool has initialized.  Feel free to do
> +	 * something fancy like completions if you don't want a
> +	 * spinning loop.
> +	 */
> +	wait_event_interruptible(uninitialized_wait, !uninitialized_count);
> +}
> +
> +#if 1 /* enable to estimate boottime entropy */
> +static uint32_t boot_log[SAMPLES_NEEDED][3];
> +static uint32_t tsc0;
> +
> +static void log_boot_entropy(struct pt_regs *regs, uint64_t cascade_hash)
> +{
> +	struct full_hash hash;
> +	int i, slot = SAMPLES_NEEDED - uninitialized_count;
> +
> +	if ((unsigned)slot > SAMPLES_NEEDED)
> +		return;
> +	if (slot == 0)
> +		tsc0 = rdtsc();
> +	hash = hash512(regs, sizeof(struct pt_regs), NULL, 0);
> +	boot_log[slot][0] = hash.h[0];
> +	boot_log[slot][1] = cascade_hash;
> +	boot_log[slot][2] = rdtsc() - tsc0;
> +	if (uninitialized_count == 1) {
> +		for (i = 0; i < SAMPLES_NEEDED; i++) {
> +			pr_info("boot_entropy %03d: %08x %08x %08x\n", i, boot_log[i][0], boot_log[i][1], boot_log[i][2]);
> +		}
> +	}
> +}
> +#else
> +static inline void log_boot_entropy(struct pt_regs *regs, uint64_t cascade_hash) {}
> +#endif
> +
> +static void produce_entropy_from_irq_regs(struct pt_regs *regs)
> +{
> +	/*
> +	 * Should be called on every interrupt.  Arguments should be
> +	 * start and size of saved register state at the time of
> +	 * interrupt.
> +	 */
> +	struct per_cpu_state *state = get_local_state();
> +	uint64_t time = get_time();
> +	struct full_hash hash;
> +
> +	/* Ratelimit to reduce interrupt overhead */
> +	if (state->p_time == time && !uninitialized_count)
> +		return;
> +	state->p_time = time;
> +
> +	/* Mix local state and new entropy from registers */
> +	hash = hash512(state, sizeof(state->half), regs, sizeof(struct pt_regs));
> +	state->half = hash.half[0];
> +
> +	/* Only mix with global state, if uncontended */
> +	if (!spin_trylock(&global_lock))
> +		return;
> +
> +	/* Mix local and global state.  */
> +	hash = hash512(&global_pool, sizeof(global_pool), &hash, sizeof(hash));
> +	state->half = hash.half[0];
> +	global_pool = hash.half[1];
> +
> +	if (uninitialized_count) {
> +		log_boot_entropy(regs, hash.h[0]);
> +		uninitialized_count--;
> +		if (uninitialized_count == 0) {
> +			pr_info("random pool fully initialized\n");
> +			wake_up(&uninitialized_wait);
> +		}
> +	}
> +	spin_unlock(&global_lock);
> +}
> +
> +static int regrand_init(void)
> +{
> +	struct full_hash hash;
> +
> +	pr_info("random pool initialization start\n");
> +	/* Interrupts before this loop may be synchronized */
> +	uninitialized_count = SAMPLES_NEEDED;
> +	/* without volatile, gcc will turn this into while (1) */
> +	while (ACCESS_ONCE(uninitialized_count)) {
> +		hash = hash512(&hash, sizeof(hash), NULL, 0);
> +	}
> +	return 0;
> +}
> +early_initcall(regrand_init);
> +
> +/*
> + * Returns 32 likely-random bytes.  No guarantees, as we don't wait
> + * for enough entropy to accumulate.  Use only if you need semi-good
> + * entropy early in boot before RNG initialization can happen.
> + */
> +static struct half_hash consume_entropy_unsafe(void)
> +{
> +	struct per_cpu_state *state;
> +	uint64_t time = get_time();
> +	struct full_hash hash;
> +
> +	preempt_disable();
> +	state = get_local_state();
> +	if (state->c_time != time || uninitialized_count) {
> +		state->c_time = time;
> +		/* Mix global pool into local pool, no locking */
> +		hash = hash512(&global_pool, sizeof(global_pool), &state->half, sizeof(state->half));
> +	} else {
> +		/* Only use local pool, reducing contention and overhead */
> +		hash = hash512(&state->half, sizeof(state->half), NULL, 0);
> +	}
> +	state->half = hash.half[0];
> +	preempt_enable();
> +	return hash.half[1];
> +}
> +
> +/* Doesn't block, use only very early in bootup */
> +void __get_random_bytes(void *buf, int nbytes)
> +{
> +	while (nbytes > 0) {
> +		struct half_hash h = consume_entropy_unsafe();
> +		memcpy(buf, &h, min_t(size_t, nbytes, sizeof(h)));
> +		buf += sizeof(h);
> +		nbytes -= sizeof(h);
> +	}
> +}
> +
> +void get_random_bytes(void *buf, int nbytes)
> +{
> +	WARN(uninitialized_count, "Using entropy before initialization");
> +	while (uninitialized_count)
> +		wait_a_while();
> +
> +	while (nbytes > 0) {
> +		struct half_hash h = consume_entropy_unsafe();
> +		memcpy(buf, &h, min_t(size_t, nbytes, sizeof(h)));
> +		buf += sizeof(h);
> +		nbytes -= sizeof(h);
> +	}
> +}
> +EXPORT_SYMBOL(get_random_bytes);
> +
> +static ssize_t _random_read(int nonblock, char __user *buf, size_t nbytes)
> +{
> +	ssize_t ret = 0, n;
> +
> +	WARN(uninitialized_count, "Using entropy before initialization");
> +	if (uninitialized_count && nonblock)
> +		return -EAGAIN;
> +	while (uninitialized_count)
> +		wait_a_while();
> +	while (nbytes > 0) {
> +		struct half_hash h = consume_entropy_unsafe();
> +		n = min_t(size_t, nbytes, sizeof(h));
> +		if (copy_to_user(buf, &h, n))
> +			return -EFAULT;
> +		buf += n;
> +		nbytes -= n;
> +		ret += n;
> +	}
> +	return ret;
> +}
> +
> +#ifdef CONFIG_SYSCTL
> +
> +/*
> + * Mostly a fake interface for compatibility with what random.c
> + * provided.  Not actually used for anything but to appease userspace.
> + */
> +#include <linux/sysctl.h>
> +
> +static int random_min_urandom_seed = 60;
> +static char sysctl_bootid[16];
> +static int entropy_avail = 8 * sizeof(struct half_hash);
> +static int sysctl_poolsize = 8 * sizeof(struct half_hash);
> +static int random_read_wakeup_bits = 64;
> +static int random_write_wakeup_bits = 896;
> +
> +/*
> + * This function is used to return both the bootid UUID, and random
> + * UUID.  The difference is in whether table->data is NULL; if it is,
> + * then a new UUID is generated and returned to the user.
> + *
> + * If the user accesses this via the proc interface, the UUID will be
> + * returned as an ASCII string in the standard UUID format; if via the
> + * sysctl system call, as 16 bytes of binary data.
> + */
> +static int proc_do_uuid(struct ctl_table *table, int write,
> +			void __user *buffer, size_t *lenp, loff_t *ppos)
> +{
> +	struct ctl_table fake_table;
> +	unsigned char buf[64], tmp_uuid[16], *uuid;
> +
> +	uuid = table->data;
> +	if (!uuid) {
> +		uuid = tmp_uuid;
> +		generate_random_uuid(uuid);
> +	} else {
> +		static DEFINE_SPINLOCK(bootid_spinlock);
> +
> +		spin_lock(&bootid_spinlock);
> +		if (!uuid[8])
> +			generate_random_uuid(uuid);
> +		spin_unlock(&bootid_spinlock);
> +	}
> +
> +	sprintf(buf, "%pU", uuid);
> +
> +	fake_table.data = buf;
> +	fake_table.maxlen = sizeof(buf);
> +
> +	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
> +}
> +
> +struct ctl_table random_table[] = {
> +	{
> +		.procname	= "poolsize",
> +		.data		= &sysctl_poolsize,
> +		.maxlen		= sizeof(int),
> +		.mode		= 0444,
> +		.proc_handler	= proc_dointvec,
> +	},
> +	{
> +		.procname	= "entropy_avail",
> +		.data		= &entropy_avail,
> +		.maxlen		= sizeof(int),
> +		.mode		= 0444,
> +		.proc_handler	= proc_dointvec,
> +	},
> +	{
> +		.procname	= "read_wakeup_threshold",
> +		.data		= &random_read_wakeup_bits,
> +		.maxlen		= sizeof(int),
> +		.mode		= 0644,
> +		.proc_handler	= proc_dointvec,
> +	},
> +	{
> +		.procname	= "write_wakeup_threshold",
> +		.data		= &random_write_wakeup_bits,
> +		.maxlen		= sizeof(int),
> +		.mode		= 0644,
> +		.proc_handler	= proc_dointvec,
> +	},
> +	{
> +		.procname	= "urandom_min_reseed_secs",
> +		.data		= &random_min_urandom_seed,
> +		.maxlen		= sizeof(int),
> +		.mode		= 0644,
> +		.proc_handler	= proc_dointvec,
> +	},
> +	{
> +		.procname	= "boot_id",
> +		.data		= &sysctl_bootid,
> +		.maxlen		= 16,
> +		.mode		= 0444,
> +		.proc_handler	= proc_do_uuid,
> +	},
> +	{
> +		.procname	= "uuid",
> +		.maxlen		= 16,
> +		.mode		= 0444,
> +		.proc_handler	= proc_do_uuid,
> +	},
> +	{ }
> +};
> +#endif 	/* CONFIG_SYSCTL */
> +
> +u64 get_random_u64(void)
> +{
> +	u64 ret;
> +	get_random_bytes(&ret, sizeof(ret));
> +	return ret;
> +}
> +EXPORT_SYMBOL(get_random_u64);
> +
> +u32 get_random_u32(void)
> +{
> +	u32 ret;
> +	get_random_bytes(&ret, sizeof(ret));
> +	return ret;
> +}
> +EXPORT_SYMBOL(get_random_u32);
> +
> +/**
> + * randomize_page - Generate a random, page aligned address
> + * @start:	The smallest acceptable address the caller will take.
> + * @range:	The size of the area, starting at @start, within which the
> + *		random address must fall.
> + *
> + * If @start + @range would overflow, @range is capped.
> + *
> + * NOTE: Historical use of randomize_range, which this replaces, presumed that
> + * @start was already page aligned.  We now align it regardless.
> + *
> + * Return: A page aligned address within [start, start + range).  On error,
> + * @start is returned.
> + */
> +unsigned long
> +randomize_page(unsigned long start, unsigned long range)
> +{
> +	if (!PAGE_ALIGNED(start)) {
> +		range -= PAGE_ALIGN(start) - start;
> +		start = PAGE_ALIGN(start);
> +	}
> +
> +	if (start > ULONG_MAX - range)
> +		range = ULONG_MAX - start;
> +
> +	range >>= PAGE_SHIFT;
> +
> +	if (range == 0)
> +		return start;
> +
> +	return start + (get_random_long() % range << PAGE_SHIFT);
> +}
> +
> +SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
> +		unsigned int, flags)
> +{
> +	int ret;
> +
> +	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
> +		return -EINVAL;
> +
> +	if (count > INT_MAX)
> +		count = INT_MAX;
> +
> +	if (uninitialized_count) {
> +		if (flags & GRND_NONBLOCK)
> +			return -EAGAIN;
> +		ret = wait_for_random_bytes();
> +		if (unlikely(ret))
> +			return ret;
> +	}
> +	return _random_read(flags & GRND_NONBLOCK, buf, count);
> +}
> +
> +static ssize_t random_read(struct file *file, char __user *buf, size_t nbytes,
> +		loff_t *ppos)
> +{
> +	return _random_read(file->f_flags & O_NONBLOCK, buf, nbytes);
> +}
> +
> +static ssize_t random_write(struct file *file, const char __user *buffer,
> +		size_t count, loff_t *ppos)
> +{
> +	return 0;
> +}
> +
> +static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
> +{
> +	int size, ent_count = 4096;
> +	int __user *p = (int __user *)arg;
> +
> +	/* just noop implementations, hardly worth the error checking */
> +	switch (cmd) {
> +	case RNDGETENTCNT:
> +		if (put_user(ent_count, p))
> +			return -EFAULT;
> +		return 0;
> +	case RNDADDTOENTCNT:
> +		if (!capable(CAP_SYS_ADMIN))
> +			return -EPERM;
> +		if (get_user(ent_count, p))
> +			return -EFAULT;
> +		return 0;
> +	case RNDADDENTROPY:
> +		if (!capable(CAP_SYS_ADMIN))
> +			return -EPERM;
> +		if (get_user(ent_count, p++))
> +			return -EFAULT;
> +		if (ent_count < 0)
> +			return -EINVAL;
> +		if (get_user(size, p++))
> +			return -EFAULT;
> +		return 0;
> +	case RNDZAPENTCNT:
> +	case RNDCLEARPOOL:
> +		if (!capable(CAP_SYS_ADMIN))
> +			return -EPERM;
> +		return 0;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static struct fasync_struct *fasync;
> +
> +static int random_fasync(int fd, struct file *filp, int on)
> +{
> +	return fasync_helper(fd, filp, on, &fasync);
> +}
> +
> +const struct file_operations random_fops = {
> +	.read  = random_read,
> +	.write = random_write,
> +	.unlocked_ioctl = random_ioctl,
> +	.fasync = random_fasync,
> +	.llseek = noop_llseek,
> +};
> +
> +const struct file_operations urandom_fops = {
> +	.read  = random_read,
> +	.write = random_write,
> +	.unlocked_ioctl = random_ioctl,
> +	.fasync = random_fasync,
> +	.llseek = noop_llseek,
> +};
> +
> +int wait_for_random_bytes(void)
> +{
> +	if (likely(!uninitialized_count))
> +		return 0;
> +	WARN(uninitialized_count, "Using entropy before initialization");
> +	return wait_event_interruptible(uninitialized_wait, !uninitialized_count);
> +}
> +EXPORT_SYMBOL(wait_for_random_bytes);
> +
> +void add_interrupt_randomness(int irq, int irq_flags)
> +{
> +	produce_entropy_from_irq_regs(get_irq_regs());
> +}
> +EXPORT_SYMBOL_GPL(add_interrupt_randomness);
> diff --git a/include/linux/genhd.h b/include/linux/genhd.h
> index ea652bfcd675..635b5723bedf 100644
> --- a/include/linux/genhd.h
> +++ b/include/linux/genhd.h
> @@ -410,8 +410,13 @@ extern void disk_flush_events(struct gendisk *disk, unsigned int mask);
>  extern unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask);
>  
>  /* drivers/char/random.c */
> +#ifdef CONFIG_REGRAND
> +static inline void add_disk_randomness(struct gendisk *disk) {}
> +static inline void rand_initialize_disk(struct gendisk *disk) {}
> +#else
>  extern void add_disk_randomness(struct gendisk *disk) __latent_entropy;
>  extern void rand_initialize_disk(struct gendisk *disk);
> +#endif
>  
>  static inline sector_t get_start_sect(struct block_device *bdev)
>  {
> diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
> index bee0827766a3..d64fc3c02ef6 100644
> --- a/include/linux/hw_random.h
> +++ b/include/linux/hw_random.h
> @@ -60,6 +60,10 @@ extern int devm_hwrng_register(struct device *dev, struct hwrng *rng);
>  extern void hwrng_unregister(struct hwrng *rng);
>  extern void devm_hwrng_unregister(struct device *dve, struct hwrng *rng);
>  /** Feed random bits into the pool. */
> +#ifdef CONFIG_REGRAND
> +static inline void add_hwgenerator_randomness(const char *buffer, size_t count, size_t entropy) {}
> +#else
>  extern void add_hwgenerator_randomness(const char *buffer, size_t count, size_t entropy);
> +#endif
>  
>  #endif /* LINUX_HWRANDOM_H_ */
> diff --git a/include/linux/random.h b/include/linux/random.h
> index eafea6a09361..0f85af279864 100644
> --- a/include/linux/random.h
> +++ b/include/linux/random.h
> @@ -17,6 +17,17 @@ struct random_ready_callback {
>  	struct module *owner;
>  };
>  
> +#ifdef CONFIG_REGRAND
> +static inline void add_device_randomness(const void *a, unsigned int b) {}
> +static inline void add_latent_entropy(void) {}
> +static inline void add_input_randomness(unsigned int type, unsigned int code,
> +		unsigned int value) {}
> +static inline int add_random_ready_callback(struct random_ready_callback *rdy) { return 0; }
> +static inline void del_random_ready_callback(struct random_ready_callback *rdy) {}
> +
> +void add_interrupt_randomness(int irq, int irq_flags);
> +void __get_random_bytes(void *buf, int nbytes);
> +#else /* CONFIG_REGRAND */
>  extern void add_device_randomness(const void *, unsigned int);
>  
>  #if defined(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) && !defined(__CHECKER__)
> @@ -27,16 +38,19 @@ static inline void add_latent_entropy(void)
>  }
>  #else
>  static inline void add_latent_entropy(void) {}
> +extern int add_random_ready_callback(struct random_ready_callback *rdy);
> +extern void del_random_ready_callback(struct random_ready_callback *rdy);
> +
> +#define __get_random_bytes get_random_bytes
>  #endif
>  
>  extern void add_input_randomness(unsigned int type, unsigned int code,
>  				 unsigned int value) __latent_entropy;
>  extern void add_interrupt_randomness(int irq, int irq_flags) __latent_entropy;
> +#endif /* CONFIG_REGRAND */
>  
>  extern void get_random_bytes(void *buf, int nbytes);
>  extern int wait_for_random_bytes(void);
> -extern int add_random_ready_callback(struct random_ready_callback *rdy);
> -extern void del_random_ready_callback(struct random_ready_callback *rdy);
>  extern void get_random_bytes_arch(void *buf, int nbytes);
>  
>  #ifndef MODULE
> @@ -72,13 +86,6 @@ static inline unsigned long get_random_long(void)
>  # define CANARY_MASK 0xffffffffUL
>  #endif
>  
> -static inline unsigned long get_random_canary(void)
> -{
> -	unsigned long val = get_random_long();
> -
> -	return val & CANARY_MASK;
> -}
> -
>  /* Calls wait_for_random_bytes() and then calls get_random_bytes(buf, nbytes).
>   * Returns the result of the call to wait_for_random_bytes. */
>  static inline int get_random_bytes_wait(void *buf, int nbytes)
> diff --git a/kernel/fork.c b/kernel/fork.c
> index 07cc743698d3..5cdd7eabc984 100644
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -562,7 +562,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
>  	set_task_stack_end_magic(tsk);
>  
>  #ifdef CONFIG_CC_STACKPROTECTOR
> -	tsk->stack_canary = get_random_canary();
> +	__get_random_bytes(&tsk->stack_canary, sizeof(tsk->stack_canary));
>  #endif
>  
>  	/*
> diff --git a/kernel/panic.c b/kernel/panic.c
> index bdd18afa19a4..e063564074af 100644
> --- a/kernel/panic.c
> +++ b/kernel/panic.c
> @@ -483,7 +483,7 @@ static u64 oops_id;
>  static int init_oops_id(void)
>  {
>  	if (!oops_id)
> -		get_random_bytes(&oops_id, sizeof(oops_id));
> +		__get_random_bytes(&oops_id, sizeof(oops_id));
>  	else
>  		oops_id++;
>  
> diff --git a/mm/slab.c b/mm/slab.c
> index 04dec48c3ed7..eba7ad862119 100644
> --- a/mm/slab.c
> +++ b/mm/slab.c
> @@ -2474,7 +2474,7 @@ static bool freelist_state_initialize(union freelist_init_state *state,
>  	unsigned int rand;
>  
>  	/* Use best entropy available to define a random shift */
> -	rand = get_random_int();
> +	__get_random_bytes(&rand, sizeof(rand));
>  
>  	/* Use a random state if the pre-computed list is not available */
>  	if (!cachep->random_seq) {
> diff --git a/mm/slab_common.c b/mm/slab_common.c
> index 80164599ca5d..de658698e010 100644
> --- a/mm/slab_common.c
> +++ b/mm/slab_common.c
> @@ -1160,6 +1160,7 @@ int cache_random_seq_create(struct kmem_cache *cachep, unsigned int count,
>  				    gfp_t gfp)
>  {
>  	struct rnd_state state;
> +	unsigned long seed;
>  
>  	if (count < 2 || cachep->random_seq)
>  		return 0;
> @@ -1169,7 +1170,8 @@ int cache_random_seq_create(struct kmem_cache *cachep, unsigned int count,
>  		return -ENOMEM;
>  
>  	/* Get best entropy at this stage of boot */
> -	prandom_seed_state(&state, get_random_long());
> +	__get_random_bytes(&seed, sizeof(seed));
> +	prandom_seed_state(&state, seed);
>  
>  	freelist_randomize(&state, cachep->random_seq, count);
>  	return 0;
> diff --git a/mm/slub.c b/mm/slub.c
> index 163352c537ab..f97387e833f7 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -1523,7 +1523,8 @@ static bool shuffle_freelist(struct kmem_cache *s, struct page *page)
>  		return false;
>  
>  	freelist_count = oo_objects(s->oo);
> -	pos = get_random_int() % freelist_count;
> +	__get_random_bytes(&pos, sizeof(pos));
> +	pos %= freelist_count;
>  
>  	page_limit = page->objects * s->size;
>  	start = fixup_red_left(s, page_address(page));
> @@ -3597,7 +3598,7 @@ static int kmem_cache_open(struct kmem_cache *s, unsigned long flags)
>  	s->flags = kmem_cache_flags(s->size, flags, s->name, s->ctor);
>  	s->reserved = 0;
>  #ifdef CONFIG_SLAB_FREELIST_HARDENED
> -	s->random = get_random_long();
> +	__get_random_bytes(&s->random, sizeof(s->random));
>  #endif
>  
>  	if (need_reserve_slab_rcu && (s->flags & SLAB_TYPESAFE_BY_RCU))
> -- 
> 2.1.4
> 

Jörn

--
It is better to die of hunger having lived without grief and fear,
than to live with a troubled spirit amid abundance.
-- Epictetus

       reply	other threads:[~2017-11-11  1:19 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20171110213039.GA6911@cork>
2017-11-11  1:17 ` Jörn Engel [this message]
     [not found] ` <20171110235212.7c2qt7tc46q7w5d2@thunk.org>
     [not found]   ` <20171111002321.GG6911@cork>
     [not found]     ` <20171111182238.yasi3rzy3ay7u4wg@thunk.org>
2017-11-11 20:13       ` [PATCH] random: add regrand Jörn Engel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171111011739.GI6911@cork \
    --to=joern@purestorage.com \
    --cc=Jason@zx2c4.com \
    --cc=hch@infradead.org \
    --cc=herbert@gondor.apana.org.au \
    --cc=hpa@zytor.com \
    --cc=jason@lakedaemon.net \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=price@mit.edu \
    --cc=schmitzmic@gmail.com \
    --cc=stephan.mueller@atsec.com \
    --cc=tytso@mit.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.