All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/12] /dev/random fixups
@ 2012-07-06 22:44 Theodore Ts'o
  2012-07-06 22:44 ` [PATCH 01/12] random: fix up sparse warnings Theodore Ts'o
                   ` (11 more replies)
  0 siblings, 12 replies; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:44 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Theodore Ts'o

This version fixes some sparse complaints; reduces stack usage in
xfer_secondary_pool; fixes a lockdep complaint caused by
get_random_bytes() getting called from interrupt context; and other
minor updates as requested by patch reviewers.

					- Ted

Linus Torvalds (1):
  random: create add_device_randomness() interface

Mark Brown (2):
  rtc: wm831x: Feed the write counter into device_add_randomness()
  mfd: wm831x: Feed the device UUID into device_add_randomness()

Theodore Ts'o (9):
  random: fix up sparse warnings
  random: make 'add_interrupt_randomness()' do something sane
  random: use lockless techniques in the interrupt path
  usb: feed USB device information to the /dev/random driver
  net: feed /dev/random with the MAC address when registering a device
  random: use the arch-specific rng in xfer_secondary_pool
  random: add new get_random_bytes_arch() function
  random: add tracepoints for easier debugging and verification
  MAINTAINERS: Theodore Ts'o is taking over the random driver

 MAINTAINERS                   |   4 +-
 drivers/char/random.c         | 274 +++++++++++++++++++++++++++++++-----------
 drivers/mfd/ab3100-core.c     |   2 -
 drivers/mfd/wm831x-otp.c      |   8 ++
 drivers/rtc/rtc-wm831x.c      |  24 +++-
 drivers/usb/core/hub.c        |   9 ++
 include/linux/random.h        |   4 +-
 include/trace/events/random.h | 134 +++++++++++++++++++++
 kernel/irq/handle.c           |   7 +-
 net/core/dev.c                |   3 +
 net/core/rtnetlink.c          |   1 +
 11 files changed, 393 insertions(+), 77 deletions(-)
 create mode 100644 include/trace/events/random.h

-- 
1.7.11.1.108.gb129051


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 01/12] random: fix up sparse warnings
  2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
@ 2012-07-06 22:44 ` Theodore Ts'o
  2012-07-06 22:44 ` [PATCH 02/12] random: make 'add_interrupt_randomness()' do something sane Theodore Ts'o
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:44 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Theodore Ts'o

Add extern and static declarations to suppress sparse warnings

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
 drivers/char/random.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 4ec04a7..cb541b9 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1279,6 +1279,7 @@ static int proc_do_uuid(ctl_table *table, int write,
 }
 
 static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
+extern ctl_table random_table[];
 ctl_table random_table[] = {
 	{
 		.procname	= "poolsize",
@@ -1344,7 +1345,7 @@ late_initcall(random_int_secret_init);
  * value is not cryptographically secure but for several uses the cost of
  * depleting entropy is too high
  */
-DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
+static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash);
 unsigned int get_random_int(void)
 {
 	__u32 *hash;
-- 
1.7.11.1.108.gb129051


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 02/12] random: make 'add_interrupt_randomness()' do something sane
  2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
  2012-07-06 22:44 ` [PATCH 01/12] random: fix up sparse warnings Theodore Ts'o
@ 2012-07-06 22:44 ` Theodore Ts'o
  2012-07-08  2:01   ` Ben Hutchings
  2012-07-06 22:44 ` [PATCH 03/12] random: use lockless techniques in the interrupt path Theodore Ts'o
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:44 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Theodore Ts'o,
	Linus Torvalds, stable

We've been moving away from add_interrupt_randomness() for various
reasons: it's too expensive to do on every interrupt, and flooding the
CPU with interrupts could theoretically cause bogus floods of entropy
from a somewhat externally controllable source.

This solves both problems by limiting the actual randomness addition
to just once a second or after 128 interrupts, whicever comes first.
During that time, the interrupt cycle data is buffered up in a per-cpu
pool.  Also, we make sure the the nonblocking pool used by urandom is
initialized before we start feeding the normal input pool.  This
assures that /dev/urandom is returning unpredictable data as soon as
possible.

(Based on an original patch by Linus, but significantly modified by
tytso.)

Tested-by: Eric Wustrow <ewust@umich.edu>
Reported-by: Eric Wustrow <ewust@umich.edu>
Reported-by: Nadia Heninger <nadiah@cs.ucsd.edu>
Reported-by: Zakir Durumeric <zakir@umich.edu>
Reported-by: J. Alex Halderman <jhalderm@umich.edu>.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: stable@vger.kernel.org
---
 drivers/char/random.c     | 103 ++++++++++++++++++++++++++++++++++++++--------
 drivers/mfd/ab3100-core.c |   2 -
 include/linux/random.h    |   2 +-
 kernel/irq/handle.c       |   7 ++--
 4 files changed, 90 insertions(+), 24 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index cb541b9..556088b 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -127,19 +127,15 @@
  *
  * 	void add_input_randomness(unsigned int type, unsigned int code,
  *                                unsigned int value);
- * 	void add_interrupt_randomness(int irq);
+ *	void add_interrupt_randomness(int irq, int irq_flags);
  * 	void add_disk_randomness(struct gendisk *disk);
  *
  * add_input_randomness() uses the input layer interrupt timing, as well as
  * the event type information from the hardware.
  *
- * add_interrupt_randomness() uses the inter-interrupt timing as random
- * inputs to the entropy pool.  Note that not all interrupts are good
- * sources of randomness!  For example, the timer interrupts is not a
- * good choice, because the periodicity of the interrupts is too
- * regular, and hence predictable to an attacker.  Network Interface
- * Controller interrupts are a better measure, since the timing of the
- * NIC interrupts are more unpredictable.
+ * add_interrupt_randomness() uses the interrupt timing as random
+ * inputs to the entropy pool. Using the cycle counters and the irq source
+ * as inputs, it feeds the randomness roughly once a second.
  *
  * add_disk_randomness() uses what amounts to the seek time of block
  * layer request events, on a per-disk_devt basis, as input to the
@@ -248,6 +244,7 @@
 #include <linux/percpu.h>
 #include <linux/cryptohash.h>
 #include <linux/fips.h>
+#include <linux/ptrace.h>
 
 #ifdef CONFIG_GENERIC_HARDIRQS
 # include <linux/irq.h>
@@ -256,6 +253,7 @@
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
+#include <asm/irq_regs.h>
 #include <asm/io.h>
 
 /*
@@ -421,7 +419,9 @@ struct entropy_store {
 	spinlock_t lock;
 	unsigned add_ptr;
 	int entropy_count;
+	int entropy_total;
 	int input_rotate;
+	unsigned int initialized:1;
 	__u8 last_data[EXTRACT_SIZE];
 };
 
@@ -454,6 +454,10 @@ static struct entropy_store nonblocking_pool = {
 	.pool = nonblocking_pool_data
 };
 
+static __u32 const twist_table[8] = {
+	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+
 /*
  * This function adds bytes into the entropy "pool".  It does not
  * update the entropy estimate.  The caller should call
@@ -467,9 +471,6 @@ static struct entropy_store nonblocking_pool = {
 static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
 				   int nbytes, __u8 out[64])
 {
-	static __u32 const twist_table[8] = {
-		0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
-		0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
 	unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
 	int input_rotate;
 	int wordmask = r->poolinfo->poolwords - 1;
@@ -528,6 +529,36 @@ static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
        mix_pool_bytes_extract(r, in, bytes, NULL);
 }
 
+struct fast_pool {
+	__u32		pool[4];
+	unsigned long	last;
+	unsigned short	count;
+	unsigned char	rotate;
+	unsigned char	last_timer_intr;
+};
+
+/*
+ * This is a fast mixing routine used by the interrupt randomness
+ * collector.  It's hardcoded for an 128 bit pool and assumes that any
+ * locks that might be needed are taken by the caller.
+ */
+static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
+{
+	const char	*bytes = in;
+	__u32		w;
+	unsigned	i = f->count;
+	unsigned	input_rotate = f->rotate;
+
+	while (nbytes--) {
+		w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^
+			f->pool[(i + 1) & 3];
+		f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7];
+		input_rotate += (i++ & 3) ? 7 : 14;
+	}
+	f->count = i;
+	f->rotate = input_rotate;
+}
+
 /*
  * Credit (or debit) the entropy store with n bits of entropy
  */
@@ -551,6 +582,12 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
 		entropy_count = r->poolinfo->POOLBITS;
 	r->entropy_count = entropy_count;
 
+	if (!r->initialized && nbits > 0) {
+		r->entropy_total += nbits;
+		if (r->entropy_total > 128)
+			r->initialized = 1;
+	}
+
 	/* should we wake readers? */
 	if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
 		wake_up_interruptible(&random_read_wait);
@@ -700,17 +737,48 @@ void add_input_randomness(unsigned int type, unsigned int code,
 }
 EXPORT_SYMBOL_GPL(add_input_randomness);
 
-void add_interrupt_randomness(int irq)
+static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
+
+void add_interrupt_randomness(int irq, int irq_flags)
 {
-	struct timer_rand_state *state;
+	struct entropy_store	*r;
+	struct fast_pool	*fast_pool = &__get_cpu_var(irq_randomness);
+	struct pt_regs		*regs = get_irq_regs();
+	unsigned long		now = jiffies;
+	__u32			input[4], cycles = get_cycles();
+
+	input[0] = cycles ^ jiffies;
+	input[1] = irq;
+	if (regs) {
+		__u64 ip = instruction_pointer(regs);
+		input[2] = ip;
+		input[3] = ip >> 32;
+	}
 
-	state = get_timer_rand_state(irq);
+	fast_mix(fast_pool, input, sizeof(input));
 
-	if (state == NULL)
+	if ((fast_pool->count & 255) &&
+	    !time_after(now, fast_pool->last + HZ))
 		return;
 
-	DEBUG_ENT("irq event %d\n", irq);
-	add_timer_randomness(state, 0x100 + irq);
+	fast_pool->last = now;
+
+	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
+	mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
+	/*
+	 * If we don't have a valid cycle counter, and we see
+	 * back-to-back timer interrupts, then skip giving credit for
+	 * any entropy.
+	 */
+	if (cycles == 0) {
+		if (irq_flags & __IRQF_TIMER) {
+			if (fast_pool->last_timer_intr)
+				return;
+			fast_pool->last_timer_intr = 1;
+		} else
+			fast_pool->last_timer_intr = 0;
+	}
+	credit_entropy_bits(r, 1);
 }
 
 #ifdef CONFIG_BLOCK
@@ -971,6 +1039,7 @@ static void init_std_data(struct entropy_store *r)
 
 	spin_lock_irqsave(&r->lock, flags);
 	r->entropy_count = 0;
+	r->entropy_total = 0;
 	spin_unlock_irqrestore(&r->lock, flags);
 
 	now = ktime_get_real();
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index 1efad20..9522d6b 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -409,8 +409,6 @@ static irqreturn_t ab3100_irq_handler(int irq, void *data)
 	u32 fatevent;
 	int err;
 
-	add_interrupt_randomness(irq);
-
 	err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1,
 				       event_regs, 3);
 	if (err)
diff --git a/include/linux/random.h b/include/linux/random.h
index 8f74538..6ef39d7 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -52,7 +52,7 @@ extern void rand_initialize_irq(int irq);
 
 extern void add_input_randomness(unsigned int type, unsigned int code,
 				 unsigned int value);
-extern void add_interrupt_randomness(int irq);
+extern void add_interrupt_randomness(int irq, int irq_flags);
 
 extern void get_random_bytes(void *buf, int nbytes);
 void generate_random_uuid(unsigned char uuid_out[16]);
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index bdb1803..131ca17 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -133,7 +133,7 @@ irqreturn_t
 handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
 {
 	irqreturn_t retval = IRQ_NONE;
-	unsigned int random = 0, irq = desc->irq_data.irq;
+	unsigned int flags = 0, irq = desc->irq_data.irq;
 
 	do {
 		irqreturn_t res;
@@ -161,7 +161,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
 
 			/* Fall through to add to randomness */
 		case IRQ_HANDLED:
-			random |= action->flags;
+			flags |= action->flags;
 			break;
 
 		default:
@@ -172,8 +172,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
 		action = action->next;
 	} while (action);
 
-	if (random & IRQF_SAMPLE_RANDOM)
-		add_interrupt_randomness(irq);
+	add_interrupt_randomness(irq, flags);
 
 	if (!noirqdebug)
 		note_interrupt(irq, desc, retval);
-- 
1.7.11.1.108.gb129051


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 03/12] random: use lockless techniques in the interrupt path
  2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
  2012-07-06 22:44 ` [PATCH 01/12] random: fix up sparse warnings Theodore Ts'o
  2012-07-06 22:44 ` [PATCH 02/12] random: make 'add_interrupt_randomness()' do something sane Theodore Ts'o
@ 2012-07-06 22:44 ` Theodore Ts'o
  2012-07-06 22:44 ` [PATCH 04/12] random: create add_device_randomness() interface Theodore Ts'o
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:44 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Theodore Ts'o, stable

The real-time Linux folks don't like add_interrupt_randomness() taking
a spinlock since it is called in the low-level interrupt routine.
This also allows us to reduce the overhead in the fast path, for the
random driver, which is the interrupt collection path.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: stable@vger.kernel.org
---
 drivers/char/random.c | 78 +++++++++++++++++++++++++--------------------------
 1 file changed, 39 insertions(+), 39 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 556088b..09a11d8 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -418,9 +418,9 @@ struct entropy_store {
 	/* read-write data: */
 	spinlock_t lock;
 	unsigned add_ptr;
+	unsigned input_rotate;
 	int entropy_count;
 	int entropy_total;
-	int input_rotate;
 	unsigned int initialized:1;
 	__u8 last_data[EXTRACT_SIZE];
 };
@@ -468,26 +468,24 @@ static __u32 const twist_table[8] = {
  * it's cheap to do so and helps slightly in the expected case where
  * the entropy is concentrated in the low-order bits.
  */
-static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
-				   int nbytes, __u8 out[64])
+static void __mix_pool_bytes(struct entropy_store *r, const void *in,
+			     int nbytes, __u8 out[64])
 {
 	unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
 	int input_rotate;
 	int wordmask = r->poolinfo->poolwords - 1;
 	const char *bytes = in;
 	__u32 w;
-	unsigned long flags;
 
-	/* Taps are constant, so we can load them without holding r->lock.  */
 	tap1 = r->poolinfo->tap1;
 	tap2 = r->poolinfo->tap2;
 	tap3 = r->poolinfo->tap3;
 	tap4 = r->poolinfo->tap4;
 	tap5 = r->poolinfo->tap5;
 
-	spin_lock_irqsave(&r->lock, flags);
-	input_rotate = r->input_rotate;
-	i = r->add_ptr;
+	smp_rmb();
+	input_rotate = ACCESS_ONCE(r->input_rotate);
+	i = ACCESS_ONCE(r->add_ptr);
 
 	/* mix one byte at a time to simplify size handling and churn faster */
 	while (nbytes--) {
@@ -514,19 +512,23 @@ static void mix_pool_bytes_extract(struct entropy_store *r, const void *in,
 		input_rotate += i ? 7 : 14;
 	}
 
-	r->input_rotate = input_rotate;
-	r->add_ptr = i;
+	ACCESS_ONCE(r->input_rotate) = input_rotate;
+	ACCESS_ONCE(r->add_ptr) = i;
+	smp_wmb();
 
 	if (out)
 		for (j = 0; j < 16; j++)
 			((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
-
-	spin_unlock_irqrestore(&r->lock, flags);
 }
 
-static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
+static void mix_pool_bytes(struct entropy_store *r, const void *in,
+			     int nbytes, __u8 out[64])
 {
-       mix_pool_bytes_extract(r, in, bytes, NULL);
+	unsigned long flags;
+
+	spin_lock_irqsave(&r->lock, flags);
+	__mix_pool_bytes(r, in, nbytes, out);
+	spin_unlock_irqrestore(&r->lock, flags);
 }
 
 struct fast_pool {
@@ -564,23 +566,22 @@ static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
  */
 static void credit_entropy_bits(struct entropy_store *r, int nbits)
 {
-	unsigned long flags;
-	int entropy_count;
+	int entropy_count, orig;
 
 	if (!nbits)
 		return;
 
-	spin_lock_irqsave(&r->lock, flags);
-
 	DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
-	entropy_count = r->entropy_count;
+retry:
+	entropy_count = orig = ACCESS_ONCE(r->entropy_count);
 	entropy_count += nbits;
 	if (entropy_count < 0) {
 		DEBUG_ENT("negative entropy/overflow\n");
 		entropy_count = 0;
 	} else if (entropy_count > r->poolinfo->POOLBITS)
 		entropy_count = r->poolinfo->POOLBITS;
-	r->entropy_count = entropy_count;
+	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+		goto retry;
 
 	if (!r->initialized && nbits > 0) {
 		r->entropy_total += nbits;
@@ -593,7 +594,6 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
 		wake_up_interruptible(&random_read_wait);
 		kill_fasync(&fasync, SIGIO, POLL_IN);
 	}
-	spin_unlock_irqrestore(&r->lock, flags);
 }
 
 /*********************************************************************
@@ -680,7 +680,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
 		sample.cycles = get_cycles();
 
 	sample.num = num;
-	mix_pool_bytes(&input_pool, &sample, sizeof(sample));
+	mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
 
 	/*
 	 * Calculate number of bits of randomness we probably added.
@@ -764,7 +764,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
 	fast_pool->last = now;
 
 	r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
-	mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
+	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL);
 	/*
 	 * If we don't have a valid cycle counter, and we see
 	 * back-to-back timer interrupts, then skip giving credit for
@@ -829,7 +829,7 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
 
 		bytes = extract_entropy(r->pull, tmp, bytes,
 					random_read_wakeup_thresh / 8, rsvd);
-		mix_pool_bytes(r, tmp, bytes);
+		mix_pool_bytes(r, tmp, bytes, NULL);
 		credit_entropy_bits(r, bytes*8);
 	}
 }
@@ -890,9 +890,11 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
 	int i;
 	__u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
 	__u8 extract[64];
+	unsigned long flags;
 
 	/* Generate a hash across the pool, 16 words (512 bits) at a time */
 	sha_init(hash);
+	spin_lock_irqsave(&r->lock, flags);
 	for (i = 0; i < r->poolinfo->poolwords; i += 16)
 		sha_transform(hash, (__u8 *)(r->pool + i), workspace);
 
@@ -905,7 +907,8 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
 	 * brute-forcing the feedback as hard as brute-forcing the
 	 * hash.
 	 */
-	mix_pool_bytes_extract(r, hash, sizeof(hash), extract);
+	__mix_pool_bytes(r, hash, sizeof(hash), extract);
+	spin_unlock_irqrestore(&r->lock, flags);
 
 	/*
 	 * To avoid duplicates, we atomically extract a portion of the
@@ -928,11 +931,10 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
 }
 
 static ssize_t extract_entropy(struct entropy_store *r, void *buf,
-			       size_t nbytes, int min, int reserved)
+				 size_t nbytes, int min, int reserved)
 {
 	ssize_t ret = 0, i;
 	__u8 tmp[EXTRACT_SIZE];
-	unsigned long flags;
 
 	xfer_secondary_pool(r, nbytes);
 	nbytes = account(r, nbytes, min, reserved);
@@ -941,6 +943,8 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
 		extract_buf(r, tmp);
 
 		if (fips_enabled) {
+			unsigned long flags;
+
 			spin_lock_irqsave(&r->lock, flags);
 			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
 				panic("Hardware RNG duplicated output!\n");
@@ -1034,22 +1038,18 @@ EXPORT_SYMBOL(get_random_bytes);
 static void init_std_data(struct entropy_store *r)
 {
 	int i;
-	ktime_t now;
-	unsigned long flags;
+	ktime_t now = ktime_get_real();
+	unsigned long rv;
 
-	spin_lock_irqsave(&r->lock, flags);
 	r->entropy_count = 0;
 	r->entropy_total = 0;
-	spin_unlock_irqrestore(&r->lock, flags);
-
-	now = ktime_get_real();
-	mix_pool_bytes(r, &now, sizeof(now));
-	for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) {
-		if (!arch_get_random_long(&flags))
+	mix_pool_bytes(r, &now, sizeof(now), NULL);
+	for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) {
+		if (!arch_get_random_long(&rv))
 			break;
-		mix_pool_bytes(r, &flags, sizeof(flags));
+		mix_pool_bytes(r, &rv, sizeof(rv), NULL);
 	}
-	mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
+	mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL);
 }
 
 static int rand_initialize(void)
@@ -1186,7 +1186,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
 		count -= bytes;
 		p += bytes;
 
-		mix_pool_bytes(r, buf, bytes);
+		mix_pool_bytes(r, buf, bytes, NULL);
 		cond_resched();
 	}
 
-- 
1.7.11.1.108.gb129051


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 04/12] random: create add_device_randomness() interface
  2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
                   ` (2 preceding siblings ...)
  2012-07-06 22:44 ` [PATCH 03/12] random: use lockless techniques in the interrupt path Theodore Ts'o
@ 2012-07-06 22:44 ` Theodore Ts'o
  2012-07-06 22:44 ` [PATCH 05/12] usb: feed USB device information to the /dev/random driver Theodore Ts'o
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:44 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Linus Torvalds,
	Theodore Ts'o, stable

From: Linus Torvalds <torvalds@linux-foundation.org>

Add a new interface, add_device_randomness() for adding data to the
random pool that is likely to differ between two devices (or possibly
even per boot).  This would be things like MAC addresses or serial
numbers, or the read-out of the RTC. This does *not* add any actual
entropy to the pool, but it initializes the pool to different values
for devices that might otherwise be identical and have very little
entropy available to them (particularly common in the embedded world).

[ Modified by tytso to mix in a timestamp, since there may be some
  variability caused by the time needed to detect/configure the hardware
  in question. ]

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: stable@vger.kernel.org
---
 drivers/char/random.c  | 28 ++++++++++++++++++++++++++++
 include/linux/random.h |  1 +
 2 files changed, 29 insertions(+)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 09a11d8..e867409 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -125,11 +125,20 @@
  * The current exported interfaces for gathering environmental noise
  * from the devices are:
  *
+ *	void add_device_randomness(const void *buf, unsigned int size);
  * 	void add_input_randomness(unsigned int type, unsigned int code,
  *                                unsigned int value);
  *	void add_interrupt_randomness(int irq, int irq_flags);
  * 	void add_disk_randomness(struct gendisk *disk);
  *
+ * add_device_randomness() is for adding data to the random pool that
+ * is likely to differ between two devices (or possibly even per boot).
+ * This would be things like MAC addresses or serial numbers, or the
+ * read-out of the RTC. This does *not* add any actual entropy to the
+ * pool, but it initializes the pool to different values for devices
+ * that might otherwise be identical and have very little entropy
+ * available to them (particularly common in the embedded world).
+ *
  * add_input_randomness() uses the input layer interrupt timing, as well as
  * the event type information from the hardware.
  *
@@ -646,6 +655,25 @@ static void set_timer_rand_state(unsigned int irq,
 }
 #endif
 
+/*
+ * Add device- or boot-specific data to the input and nonblocking
+ * pools to help initialize them to unique values.
+ *
+ * None of this adds any entropy, it is meant to avoid the
+ * problem of the nonblocking pool having similar initial state
+ * across largely identical devices.
+ */
+void add_device_randomness(const void *buf, unsigned int size)
+{
+	unsigned long time = get_cycles() ^ jiffies;
+
+	mix_pool_bytes(&input_pool, buf, size, NULL);
+	mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
+	mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
+	mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
+}
+EXPORT_SYMBOL(add_device_randomness);
+
 static struct timer_rand_state input_timer_state;
 
 /*
diff --git a/include/linux/random.h b/include/linux/random.h
index 6ef39d7..e14b438 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -50,6 +50,7 @@ struct rnd_state {
 
 extern void rand_initialize_irq(int irq);
 
+extern void add_device_randomness(const void *, unsigned int);
 extern void add_input_randomness(unsigned int type, unsigned int code,
 				 unsigned int value);
 extern void add_interrupt_randomness(int irq, int irq_flags);
-- 
1.7.11.1.108.gb129051


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 05/12] usb: feed USB device information to the /dev/random driver
  2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
                   ` (3 preceding siblings ...)
  2012-07-06 22:44 ` [PATCH 04/12] random: create add_device_randomness() interface Theodore Ts'o
@ 2012-07-06 22:44 ` Theodore Ts'o
  2012-07-06 23:02   ` Jonathan Nieder
  2012-07-06 22:44 ` [PATCH 06/12] net: feed /dev/random with the MAC address when registering a device Theodore Ts'o
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:44 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Theodore Ts'o,
	Linus Torvalds, stable

Send the USB device's serial, product, and manufacturer strings to the
/dev/random driver to help seed its pools.

Cc: Linus Torvalds <torvalds@linux-foundation.org>
Acked-by: Greg KH <greg@kroah.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: stable@vger.kernel.org
---
 drivers/usb/core/hub.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 25a7422..7f380ff 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -24,6 +24,7 @@
 #include <linux/kthread.h>
 #include <linux/mutex.h>
 #include <linux/freezer.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -2173,6 +2174,14 @@ int usb_new_device(struct usb_device *udev)
 	/* Tell the world! */
 	announce_device(udev);
 
+	if (udev->serial)
+		add_device_randomness(udev->serial, strlen(udev->serial));
+	if (udev->product)
+		add_device_randomness(udev->product, strlen(udev->product));
+	if (udev->manufacturer)
+		add_device_randomness(udev->manufacturer,
+				      strlen(udev->manufacturer));
+
 	device_enable_async_suspend(&udev->dev);
 
 	/*
-- 
1.7.11.1.108.gb129051


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 06/12] net: feed /dev/random with the MAC address when registering a device
  2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
                   ` (4 preceding siblings ...)
  2012-07-06 22:44 ` [PATCH 05/12] usb: feed USB device information to the /dev/random driver Theodore Ts'o
@ 2012-07-06 22:44 ` Theodore Ts'o
  2012-07-06 22:44 ` [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool Theodore Ts'o
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:44 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Theodore Ts'o, David Miller,
	Linus Torvalds, stable

Cc: David Miller <davem@davemloft.net>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: stable@vger.kernel.org
---
 net/core/dev.c       | 3 +++
 net/core/rtnetlink.c | 1 +
 2 files changed, 4 insertions(+)

diff --git a/net/core/dev.c b/net/core/dev.c
index 6df2140..bdd1e88 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1172,6 +1172,7 @@ static int __dev_open(struct net_device *dev)
 		net_dmaengine_get();
 		dev_set_rx_mode(dev);
 		dev_activate(dev);
+		add_device_randomness(dev->dev_addr, dev->addr_len);
 	}
 
 	return ret;
@@ -4763,6 +4764,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
 	err = ops->ndo_set_mac_address(dev, sa);
 	if (!err)
 		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+	add_device_randomness(dev->dev_addr, dev->addr_len);
 	return err;
 }
 EXPORT_SYMBOL(dev_set_mac_address);
@@ -5541,6 +5543,7 @@ int register_netdevice(struct net_device *dev)
 	dev_init_scheduler(dev);
 	dev_hold(dev);
 	list_netdevice(dev);
+	add_device_randomness(dev->dev_addr, dev->addr_len);
 
 	/* Notify protocols, that a new device appeared. */
 	ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 21318d1..f058e59 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1378,6 +1378,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 			goto errout;
 		send_addr_notify = 1;
 		modified = 1;
+		add_device_randomness(dev->dev_addr, dev->addr_len);
 	}
 
 	if (tb[IFLA_MTU]) {
-- 
1.7.11.1.108.gb129051


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool
  2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
                   ` (5 preceding siblings ...)
  2012-07-06 22:44 ` [PATCH 06/12] net: feed /dev/random with the MAC address when registering a device Theodore Ts'o
@ 2012-07-06 22:44 ` Theodore Ts'o
  2012-07-07 17:11   ` [PATCH] random: only use gathered bytes from arch_get_random_long Kees Cook
  2012-07-08  1:06   ` [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool Ben Hutchings
  2012-07-06 22:45 ` [PATCH 08/12] random: add new get_random_bytes_arch() function Theodore Ts'o
                   ` (4 subsequent siblings)
  11 siblings, 2 replies; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:44 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Theodore Ts'o, stable

If the CPU supports a hardware random number generator, use it in
xfer_secondary_pool(), where it will significantly improve things and
where we can afford it.

Also, remove the use of the arch-specific rng in
add_timer_randomness(), since the call is significantly slower than
get_cycles(), and we're much better off using it in
xfer_secondary_pool() anyway.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: stable@vger.kernel.org
---
 drivers/char/random.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index e867409..c39bdc4 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -702,11 +702,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
 		goto out;
 
 	sample.jiffies = jiffies;
-
-	/* Use arch random value, fall back to cycles */
-	if (!arch_get_random_int(&sample.cycles))
-		sample.cycles = get_cycles();
-
+	sample.cycles = get_cycles();
 	sample.num = num;
 	mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
 
@@ -838,7 +834,11 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
  */
 static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
 {
-	__u32 tmp[OUTPUT_POOL_WORDS];
+	union {
+		__u32	tmp[OUTPUT_POOL_WORDS];
+		long	hwrand[4];
+	} u;
+	int	i;
 
 	if (r->pull && r->entropy_count < nbytes * 8 &&
 	    r->entropy_count < r->poolinfo->POOLBITS) {
@@ -849,17 +849,22 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
 		/* pull at least as many as BYTES as wakeup BITS */
 		bytes = max_t(int, bytes, random_read_wakeup_thresh / 8);
 		/* but never more than the buffer size */
-		bytes = min_t(int, bytes, sizeof(tmp));
+		bytes = min_t(int, bytes, sizeof(u.tmp));
 
 		DEBUG_ENT("going to reseed %s with %d bits "
 			  "(%d of %d requested)\n",
 			  r->name, bytes * 8, nbytes * 8, r->entropy_count);
 
-		bytes = extract_entropy(r->pull, tmp, bytes,
+		bytes = extract_entropy(r->pull, u.tmp, bytes,
 					random_read_wakeup_thresh / 8, rsvd);
-		mix_pool_bytes(r, tmp, bytes, NULL);
+		mix_pool_bytes(r, u.tmp, bytes, NULL);
 		credit_entropy_bits(r, bytes*8);
 	}
+	for (i = 0; i < 4; i++)
+		if (arch_get_random_long(&u.hwrand[i]))
+			break;
+	if (i)
+		mix_pool_bytes(r, &u.hwrand, sizeof(u.hwrand), 0);
 }
 
 /*
-- 
1.7.11.1.108.gb129051


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 08/12] random: add new get_random_bytes_arch() function
  2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
                   ` (6 preceding siblings ...)
  2012-07-06 22:44 ` [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool Theodore Ts'o
@ 2012-07-06 22:45 ` Theodore Ts'o
  2012-07-06 22:45 ` [PATCH 09/12] random: add tracepoints for easier debugging and verification Theodore Ts'o
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:45 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Theodore Ts'o, stable

Create a new function, get_random_bytes_arch() which will use the
architecture-specific hardware random number generator if it is
present.  Change get_random_bytes() to not use the HW RNG, even if it
is avaiable.

The reason for this is that the hw random number generator is fast (if
it is present), but it requires that we trust the hardware
manufacturer to have not put in a back door.  (For example, an
increasing counter encrypted by an AES key known to the NSA.)

It's unlikely that Intel (for example) was paid off by the US
Government to do this, but it's impossible for them to prove otherwise
--- especially since Bull Mountain is documented to use AES as a
whitener.  Hence, the output of an evil, trojan-horse version of
RDRAND is statistically indistinguishable from an RDRAND implemented
to the specifications claimed by Intel.  Short of using a tunnelling
electronic microscope to reverse engineer an Ivy Bridge chip and
disassembling and analyzing the CPU microcode, there's no way for us
to tell for sure.

Since users of get_random_bytes() in the Linux kernel need to be able
to support hardware systems where the HW RNG is not present, most
time-sensitive users of this interface have already created their own
cryptographic RNG interface which uses get_random_bytes() as a seed.
So it's much better to use the HW RNG to improve the existing random
number generator, by mixing in any entropy returned by the HW RNG into
/dev/random's entropy pool, but to always _use_ /dev/random's entropy
pool.

This way we get almost of the benefits of the HW RNG without any
potential liabilities.  The only benefits we forgo is the
speed/performance enhancements --- and generic kernel code can't
depend on depend on get_random_bytes() having the speed of a HW RNG
anyway.

For those places that really want access to the arch-specific HW RNG,
if it is available, we provide get_random_bytes_arch().

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Cc: stable@vger.kernel.org
---
 drivers/char/random.c  | 29 ++++++++++++++++++++++++-----
 include/linux/random.h |  1 +
 2 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index c39bdc4..79c105a 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1036,17 +1036,34 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
 
 /*
  * This function is the exported kernel interface.  It returns some
- * number of good random numbers, suitable for seeding TCP sequence
- * numbers, etc.
+ * number of good random numbers, suitable for key generation, seeding
+ * TCP sequence numbers, etc.  It does not use the hw random number
+ * generator, if available; use get_random_bytes_arch() for that.
  */
 void get_random_bytes(void *buf, int nbytes)
 {
+	extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
+}
+EXPORT_SYMBOL(get_random_bytes);
+
+/*
+ * This function will use the architecture-specific hardware random
+ * number generator if it is available.  The arch-specific hw RNG will
+ * almost certainly be faster than what we can do in software, but it
+ * is impossible to verify that it is implemented securely (as
+ * opposed, to, say, the AES encryption of a sequence number using a
+ * key known by the NSA).  So it's useful if we need the speed, but
+ * only if we're willing to trust the hardware manufacturer not to
+ * have put in a back door.
+ */
+void get_random_bytes_arch(void *buf, int nbytes)
+{
 	char *p = buf;
 
 	while (nbytes) {
 		unsigned long v;
 		int chunk = min(nbytes, (int)sizeof(unsigned long));
-		
+
 		if (!arch_get_random_long(&v))
 			break;
 		
@@ -1055,9 +1072,11 @@ void get_random_bytes(void *buf, int nbytes)
 		nbytes -= chunk;
 	}
 
-	extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
+	if (nbytes)
+		extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);
 }
-EXPORT_SYMBOL(get_random_bytes);
+EXPORT_SYMBOL(get_random_bytes_arch);
+
 
 /*
  * init_std_data - initialize pool with system data
diff --git a/include/linux/random.h b/include/linux/random.h
index e14b438..29e217a 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -56,6 +56,7 @@ extern void add_input_randomness(unsigned int type, unsigned int code,
 extern void add_interrupt_randomness(int irq, int irq_flags);
 
 extern void get_random_bytes(void *buf, int nbytes);
+extern void get_random_bytes_arch(void *buf, int nbytes);
 void generate_random_uuid(unsigned char uuid_out[16]);
 
 #ifndef MODULE
-- 
1.7.11.1.108.gb129051


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 09/12] random: add tracepoints for easier debugging and verification
  2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
                   ` (7 preceding siblings ...)
  2012-07-06 22:45 ` [PATCH 08/12] random: add new get_random_bytes_arch() function Theodore Ts'o
@ 2012-07-06 22:45 ` Theodore Ts'o
  2012-07-06 22:45 ` [PATCH 10/12] MAINTAINERS: Theodore Ts'o is taking over the random driver Theodore Ts'o
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:45 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Theodore Ts'o

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
 drivers/char/random.c         |  26 ++++++--
 include/trace/events/random.h | 134 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 156 insertions(+), 4 deletions(-)
 create mode 100644 include/trace/events/random.h

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 79c105a..aaf4629 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -265,6 +265,9 @@
 #include <asm/irq_regs.h>
 #include <asm/io.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/random.h>
+
 /*
  * Configuration information
  */
@@ -477,8 +480,8 @@ static __u32 const twist_table[8] = {
  * it's cheap to do so and helps slightly in the expected case where
  * the entropy is concentrated in the low-order bits.
  */
-static void __mix_pool_bytes(struct entropy_store *r, const void *in,
-			     int nbytes, __u8 out[64])
+static void _mix_pool_bytes(struct entropy_store *r, const void *in,
+			    int nbytes, __u8 out[64])
 {
 	unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
 	int input_rotate;
@@ -530,13 +533,21 @@ static void __mix_pool_bytes(struct entropy_store *r, const void *in,
 			((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
 }
 
-static void mix_pool_bytes(struct entropy_store *r, const void *in,
+static void __mix_pool_bytes(struct entropy_store *r, const void *in,
 			     int nbytes, __u8 out[64])
 {
+	trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_);
+	_mix_pool_bytes(r, in, nbytes, out);
+}
+
+static void mix_pool_bytes(struct entropy_store *r, const void *in,
+			   int nbytes, __u8 out[64])
+{
 	unsigned long flags;
 
+	trace_mix_pool_bytes(r->name, nbytes, _RET_IP_);
 	spin_lock_irqsave(&r->lock, flags);
-	__mix_pool_bytes(r, in, nbytes, out);
+	_mix_pool_bytes(r, in, nbytes, out);
 	spin_unlock_irqrestore(&r->lock, flags);
 }
 
@@ -584,6 +595,7 @@ static void credit_entropy_bits(struct entropy_store *r, int nbits)
 retry:
 	entropy_count = orig = ACCESS_ONCE(r->entropy_count);
 	entropy_count += nbits;
+
 	if (entropy_count < 0) {
 		DEBUG_ENT("negative entropy/overflow\n");
 		entropy_count = 0;
@@ -598,6 +610,9 @@ retry:
 			r->initialized = 1;
 	}
 
+	trace_credit_entropy_bits(r->name, nbits, entropy_count,
+				  r->entropy_total, _RET_IP_);
+
 	/* should we wake readers? */
 	if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
 		wake_up_interruptible(&random_read_wait);
@@ -969,6 +984,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
 	ssize_t ret = 0, i;
 	__u8 tmp[EXTRACT_SIZE];
 
+	trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
 	xfer_secondary_pool(r, nbytes);
 	nbytes = account(r, nbytes, min, reserved);
 
@@ -1003,6 +1019,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
 	ssize_t ret = 0, i;
 	__u8 tmp[EXTRACT_SIZE];
 
+	trace_extract_entropy_user(r->name, nbytes, r->entropy_count, _RET_IP_);
 	xfer_secondary_pool(r, nbytes);
 	nbytes = account(r, nbytes, 0, 0);
 
@@ -1060,6 +1077,7 @@ void get_random_bytes_arch(void *buf, int nbytes)
 {
 	char *p = buf;
 
+	trace_get_random_bytes(nbytes, _RET_IP_);
 	while (nbytes) {
 		unsigned long v;
 		int chunk = min(nbytes, (int)sizeof(unsigned long));
diff --git a/include/trace/events/random.h b/include/trace/events/random.h
new file mode 100644
index 0000000..422df19
--- /dev/null
+++ b/include/trace/events/random.h
@@ -0,0 +1,134 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM random
+
+#if !defined(_TRACE_RANDOM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_RANDOM_H
+
+#include <linux/writeback.h>
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(random__mix_pool_bytes,
+	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+
+	TP_ARGS(pool_name, bytes, IP),
+
+	TP_STRUCT__entry(
+		__field( const char *,	pool_name		)
+		__field(	  int,	bytes			)
+		__field(unsigned long,	IP			)
+	),
+
+	TP_fast_assign(
+		__entry->pool_name	= pool_name;
+		__entry->bytes		= bytes;
+		__entry->IP		= IP;
+	),
+
+	TP_printk("%s pool: bytes %d caller %pF",
+		  __entry->pool_name, __entry->bytes, (void *)__entry->IP)
+);
+
+DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes,
+	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+
+	TP_ARGS(pool_name, bytes, IP)
+);
+
+DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,
+	TP_PROTO(const char *pool_name, int bytes, unsigned long IP),
+
+	TP_ARGS(pool_name, bytes, IP)
+);
+
+TRACE_EVENT(credit_entropy_bits,
+	TP_PROTO(const char *pool_name, int bits, int entropy_count,
+		 int entropy_total, unsigned long IP),
+
+	TP_ARGS(pool_name, bits, entropy_count, entropy_total, IP),
+
+	TP_STRUCT__entry(
+		__field( const char *,	pool_name		)
+		__field(	  int,	bits			)
+		__field(	  int,	entropy_count		)
+		__field(	  int,	entropy_total		)
+		__field(unsigned long,	IP			)
+	),
+
+	TP_fast_assign(
+		__entry->pool_name	= pool_name;
+		__entry->bits		= bits;
+		__entry->entropy_count	= entropy_count;
+		__entry->entropy_total	= entropy_total;
+		__entry->IP		= IP;
+	),
+
+	TP_printk("%s pool: bits %d entropy_count %d entropy_total %d "
+		  "caller %pF", __entry->pool_name, __entry->bits,
+		  __entry->entropy_count, __entry->entropy_total,
+		  (void *)__entry->IP)
+);
+
+TRACE_EVENT(get_random_bytes,
+	TP_PROTO(int nbytes, unsigned long IP),
+
+	TP_ARGS(nbytes, IP),
+
+	TP_STRUCT__entry(
+		__field(	  int,	nbytes			)
+		__field(unsigned long,	IP			)
+	),
+
+	TP_fast_assign(
+		__entry->nbytes		= nbytes;
+		__entry->IP		= IP;
+	),
+
+	TP_printk("nbytes %d caller %pF", __entry->nbytes, (void *)__entry->IP)
+);
+
+DECLARE_EVENT_CLASS(random__extract_entropy,
+	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
+		 unsigned long IP),
+
+	TP_ARGS(pool_name, nbytes, entropy_count, IP),
+
+	TP_STRUCT__entry(
+		__field( const char *,	pool_name		)
+		__field(	  int,	nbytes			)
+		__field(	  int,	entropy_count		)
+		__field(unsigned long,	IP			)
+	),
+
+	TP_fast_assign(
+		__entry->pool_name	= pool_name;
+		__entry->nbytes		= nbytes;
+		__entry->entropy_count	= entropy_count;
+		__entry->IP		= IP;
+	),
+
+	TP_printk("%s pool: nbytes %d entropy_count %d caller %pF",
+		  __entry->pool_name, __entry->nbytes, __entry->entropy_count,
+		  (void *)__entry->IP)
+);
+
+
+DEFINE_EVENT(random__extract_entropy, extract_entropy,
+	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
+		 unsigned long IP),
+
+	TP_ARGS(pool_name, nbytes, entropy_count, IP)
+);
+
+DEFINE_EVENT(random__extract_entropy, extract_entropy_user,
+	TP_PROTO(const char *pool_name, int nbytes, int entropy_count,
+		 unsigned long IP),
+
+	TP_ARGS(pool_name, nbytes, entropy_count, IP)
+);
+
+
+
+#endif /* _TRACE_RANDOM_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
-- 
1.7.11.1.108.gb129051


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 10/12] MAINTAINERS: Theodore Ts'o is taking over the random driver
  2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
                   ` (8 preceding siblings ...)
  2012-07-06 22:45 ` [PATCH 09/12] random: add tracepoints for easier debugging and verification Theodore Ts'o
@ 2012-07-06 22:45 ` Theodore Ts'o
  2012-07-06 22:45 ` [PATCH 11/12] rtc: wm831x: Feed the write counter into device_add_randomness() Theodore Ts'o
  2012-07-06 22:45 ` [PATCH 12/12] mfd: wm831x: Feed the device UUID " Theodore Ts'o
  11 siblings, 0 replies; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:45 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Theodore Ts'o, Matt Mackall

Matt Mackall stepped down as the /dev/random driver maintainer last
year, so Theodore Ts'o is taking back the /dev/random driver.

Cc: Matt Mackall <mpm@selenic.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
 MAINTAINERS | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index eb22272..808cceb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3159,9 +3159,9 @@ F:	drivers/hwmon/
 F:	include/linux/hwmon*.h
 
 HARDWARE RANDOM NUMBER GENERATOR CORE
-M:	Matt Mackall <mpm@selenic.com>
+M:	Theodore Ts'o" <tytso@mit.edu>
 M:	Herbert Xu <herbert@gondor.apana.org.au>
-S:	Odd fixes
+S:	Maintained
 F:	Documentation/hw_random.txt
 F:	drivers/char/hw_random/
 F:	include/linux/hw_random.h
-- 
1.7.11.1.108.gb129051


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 11/12] rtc: wm831x: Feed the write counter into device_add_randomness()
  2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
                   ` (9 preceding siblings ...)
  2012-07-06 22:45 ` [PATCH 10/12] MAINTAINERS: Theodore Ts'o is taking over the random driver Theodore Ts'o
@ 2012-07-06 22:45 ` Theodore Ts'o
  2012-07-06 22:45 ` [PATCH 12/12] mfd: wm831x: Feed the device UUID " Theodore Ts'o
  11 siblings, 0 replies; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:45 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Mark Brown, Theodore Ts'o, stable

From: Mark Brown <broonie@opensource.wolfsonmicro.com>

The tamper evident features of the RTC include the "write counter" which
is a pseudo-random number regenerated whenever we set the RTC. Since this
value is unpredictable it should provide some useful seeding to the random
number generator.

Only do this on boot since the goal is to seed the pool rather than add
useful entropy.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@vger.kernel.org
---
 drivers/rtc/rtc-wm831x.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c
index 59c6245..ea5c6f8 100644
--- a/drivers/rtc/rtc-wm831x.c
+++ b/drivers/rtc/rtc-wm831x.c
@@ -24,7 +24,7 @@
 #include <linux/mfd/wm831x/core.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
-
+#include <linux/random.h>
 
 /*
  * R16416 (0x4020) - RTC Write Counter
@@ -96,6 +96,26 @@ struct wm831x_rtc {
 	unsigned int alarm_enabled:1;
 };
 
+static void wm831x_rtc_add_randomness(struct wm831x *wm831x)
+{
+	int ret;
+	u16 reg;
+
+	/*
+	 * The write counter contains a pseudo-random number which is
+	 * regenerated every time we set the RTC so it should be a
+	 * useful per-system source of entropy.
+	 */
+	ret = wm831x_reg_read(wm831x, WM831X_RTC_WRITE_COUNTER);
+	if (ret >= 0) {
+		reg = ret;
+		add_device_randomness(&reg, sizeof(reg));
+	} else {
+		dev_warn(wm831x->dev, "Failed to read RTC write counter: %d\n",
+			 ret);
+	}
+}
+
 /*
  * Read current time and date in RTC
  */
@@ -431,6 +451,8 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
 			alm_irq, ret);
 	}
 
+	wm831x_rtc_add_randomness(wm831x);
+
 	return 0;
 
 err:
-- 
1.7.11.1.108.gb129051


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 12/12] mfd: wm831x: Feed the device UUID into device_add_randomness()
  2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
                   ` (10 preceding siblings ...)
  2012-07-06 22:45 ` [PATCH 11/12] rtc: wm831x: Feed the write counter into device_add_randomness() Theodore Ts'o
@ 2012-07-06 22:45 ` Theodore Ts'o
  11 siblings, 0 replies; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 22:45 UTC (permalink / raw)
  To: Linux Kernel Developers List
  Cc: ewust, zakir, nadiah, jhalderm, Mark Brown, Theodore Ts'o, stable

From: Mark Brown <broonie@opensource.wolfsonmicro.com>

wm831x devices contain a unique ID value. Feed this into the newly added
device_add_randomness() to add some per device seed data to the pool.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@vger.kernel.org
---
 drivers/mfd/wm831x-otp.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/mfd/wm831x-otp.c b/drivers/mfd/wm831x-otp.c
index f742745..b90f3e0 100644
--- a/drivers/mfd/wm831x-otp.c
+++ b/drivers/mfd/wm831x-otp.c
@@ -18,6 +18,7 @@
 #include <linux/bcd.h>
 #include <linux/delay.h>
 #include <linux/mfd/core.h>
+#include <linux/random.h>
 
 #include <linux/mfd/wm831x/core.h>
 #include <linux/mfd/wm831x/otp.h>
@@ -66,6 +67,7 @@ static DEVICE_ATTR(unique_id, 0444, wm831x_unique_id_show, NULL);
 
 int wm831x_otp_init(struct wm831x *wm831x)
 {
+	char uuid[WM831X_UNIQUE_ID_LEN];
 	int ret;
 
 	ret = device_create_file(wm831x->dev, &dev_attr_unique_id);
@@ -73,6 +75,12 @@ int wm831x_otp_init(struct wm831x *wm831x)
 		dev_err(wm831x->dev, "Unique ID attribute not created: %d\n",
 			ret);
 
+	ret = wm831x_unique_id_read(wm831x, uuid);
+	if (ret == 0)
+		add_device_randomness(uuid, sizeof(uuid));
+	else
+		dev_err(wm831x->dev, "Failed to read UUID: %d\n", ret);
+
 	return ret;
 }
 
-- 
1.7.11.1.108.gb129051


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 05/12] usb: feed USB device information to the /dev/random driver
  2012-07-06 22:44 ` [PATCH 05/12] usb: feed USB device information to the /dev/random driver Theodore Ts'o
@ 2012-07-06 23:02   ` Jonathan Nieder
  2012-07-06 23:18     ` Greg KH
  2012-07-06 23:26     ` Theodore Ts'o
  0 siblings, 2 replies; 24+ messages in thread
From: Jonathan Nieder @ 2012-07-06 23:02 UTC (permalink / raw)
  To: Theodore Ts'o
  Cc: Linux Kernel Developers List, ewust, zakir, nadiah, jhalderm,
	Linus Torvalds, stable

Hi,

Theodore Ts'o wrote:

> Send the USB device's serial, product, and manufacturer strings to the
> /dev/random driver to help seed its pools.
>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> Acked-by: Greg KH <greg@kroah.com>
> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
> Cc: stable@vger.kernel.org

Why cc: stable@?  Does this fix a build error, oops, hang, data
corruption, real security issue, or other critical "oh, that's not
good" bug?

(I can imagine some reasons but I'm asking because it's not spelled
out.)

Thanks,
Jonathan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 05/12] usb: feed USB device information to the /dev/random driver
  2012-07-06 23:02   ` Jonathan Nieder
@ 2012-07-06 23:18     ` Greg KH
  2012-07-06 23:26     ` Theodore Ts'o
  1 sibling, 0 replies; 24+ messages in thread
From: Greg KH @ 2012-07-06 23:18 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Theodore Ts'o, Linux Kernel Developers List, ewust, zakir,
	nadiah, jhalderm, Linus Torvalds, stable

On Fri, Jul 06, 2012 at 06:02:18PM -0500, Jonathan Nieder wrote:
> Hi,
> 
> Theodore Ts'o wrote:
> 
> > Send the USB device's serial, product, and manufacturer strings to the
> > /dev/random driver to help seed its pools.
> >
> > Cc: Linus Torvalds <torvalds@linux-foundation.org>
> > Acked-by: Greg KH <greg@kroah.com>
> > Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
> > Cc: stable@vger.kernel.org
> 
> Why cc: stable@?  Does this fix a build error, oops, hang, data
> corruption, real security issue, or other critical "oh, that's not
> good" bug?
> 
> (I can imagine some reasons but I'm asking because it's not spelled
> out.)

It's part of the larger series that resolves issues with the random
number generator at boot time.  You want these patches backported, read
the original report for why.

hope this helps,

greg k-h

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 05/12] usb: feed USB device information to the /dev/random driver
  2012-07-06 23:02   ` Jonathan Nieder
  2012-07-06 23:18     ` Greg KH
@ 2012-07-06 23:26     ` Theodore Ts'o
  2012-07-07  1:08       ` Jonathan Nieder
  1 sibling, 1 reply; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-06 23:26 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: Linux Kernel Developers List, ewust, zakir, nadiah, jhalderm,
	Linus Torvalds, stable

On Fri, Jul 06, 2012 at 06:02:18PM -0500, Jonathan Nieder wrote:
> 
> Why cc: stable@?  Does this fix a build error, oops, hang, data
> corruption, real security issue, or other critical "oh, that's not
> good" bug?

All of the /dev/random patches in this patch series that were marked
for the stable backports are to address a security issue.  See:
https://factorable.net/

The main hope is that we can get the embedded device manufacturers to
grab these patches sooner rather than later, so getting them into the
stable backport trees is just as important, if not more so, than
getting them into v3.5.

While these patches are designed to do as much as we can without
assuming any fixes in userspace, and the weak kea vulnerabilities are
much more obviously detectable in embedded devices with close to zero
available entropy, ideally there are improvements that can and should
be done in upstream userspace packages as well as in the packaging and
installation scripts for more general-purpose server and workstation
distributions.

For example, ssh key generation should happen as late as possible;
ideally, some time *after* the networking has been brought up.  If the
ssh keys get generated while the installer is running, before the
kernel has a chance to collect entropy --- especially if the user
chooses to do this with the machine off the network --- well, that's
unfortunate.  The same is true for the generation of remote
administration keys for ntpd and bind.

See the extended version of the research paper for more discussion on
remediation possibilities up and down the OS stack.

Regards,

						- Ted

P.S.  This vulnerability was blogged about a few months ago, and it's
about to be presented at the upcoming Usenix Security Symposium next
month.  Hence, nothing discussed here or in the patch set is a secret.
Please feel free to forward this to any distribution security teams
you think appropriate.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 05/12] usb: feed USB device information to the /dev/random driver
  2012-07-06 23:26     ` Theodore Ts'o
@ 2012-07-07  1:08       ` Jonathan Nieder
  0 siblings, 0 replies; 24+ messages in thread
From: Jonathan Nieder @ 2012-07-07  1:08 UTC (permalink / raw)
  To: Theodore Ts'o
  Cc: Linux Kernel Developers List, ewust, zakir, nadiah, jhalderm,
	Linus Torvalds, stable

Hi,

Theodore Ts'o wrote:
> On Fri, Jul 06, 2012 at 06:02:18PM -0500, Jonathan Nieder wrote:

>> Why cc: stable@?  Does this fix a build error, oops, hang, data
>> corruption, real security issue, or other critical "oh, that's not
>> good" bug?
>
> All of the /dev/random patches in this patch series that were marked
> for the stable backports are to address a security issue.  See:
> https://factorable.net/

Thanks for explaining.  If there's occasion for a reroll (I'm guessing
there won't be) then it would be nice to mention this in the commit
messages.

[...]
> While these patches are designed to do as much as we can without
> assuming any fixes in userspace, and the weak kea vulnerabilities are
> much more obviously detectable in embedded devices with close to zero
> available entropy, ideally there are improvements that can and should
> be done in upstream userspace packages as well as in the packaging and
> installation scripts for more general-purpose server and workstation
> distributions.
>
> For example, ssh key generation should happen as late as possible;
> ideally, some time *after* the networking has been brought up.
[...]
>               The same is true for the generation of remote
> administration keys for ntpd and bind.

Very much agreed.  These patches look like an improvement but on
diskless systems without a hardware RNG it still seems possible for
someone with knowledge of the hardware configuration to predict the
generator state.

Except that patch 2 improves matters a lot.

Thanks for your work and kindness,
Jonathan

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH] random: only use gathered bytes from arch_get_random_long
  2012-07-06 22:44 ` [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool Theodore Ts'o
@ 2012-07-07 17:11   ` Kees Cook
  2012-07-07 18:23     ` Theodore Ts'o
  2012-07-08  1:06   ` [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool Ben Hutchings
  1 sibling, 1 reply; 24+ messages in thread
From: Kees Cook @ 2012-07-07 17:11 UTC (permalink / raw)
  To: Theodore Ts'o
  Cc: Linux Kernel Developers List, ewust, zakir, nadiah, jhalderm, stable

While very unlikely, it is possible for arch_get_random_long() to fail
in the middle of the loop in xfer_secondary_pool(), which would mean
that the loop could stop with only part of u.hwrand populated, leading
to mix_pool_bytes() injecting uninitialized or already injected bytes
instead of fresh bytes. This changes the mix_pool_bytes() call to only
inject the successfully gathered bytes.

Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: stable@vger.kernel.org
---
Should be applied on top of the tytso/random dev branch.
---
 drivers/char/random.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index aaf4629..6fc3128 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -879,7 +879,7 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
 		if (arch_get_random_long(&u.hwrand[i]))
 			break;
 	if (i)
-		mix_pool_bytes(r, &u.hwrand, sizeof(u.hwrand), 0);
+		mix_pool_bytes(r, &u.hwrand, i * sizeof(u.hwrand[0]), 0);
 }
 
 /*
-- 
1.7.0.4

-- 
Kees Cook
Chrome OS Security

^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH] random: only use gathered bytes from arch_get_random_long
  2012-07-07 17:11   ` [PATCH] random: only use gathered bytes from arch_get_random_long Kees Cook
@ 2012-07-07 18:23     ` Theodore Ts'o
  2012-07-07 23:20       ` Kees Cook
  0 siblings, 1 reply; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-07 18:23 UTC (permalink / raw)
  To: Kees Cook
  Cc: Linux Kernel Developers List, ewust, zakir, nadiah, jhalderm, stable

On Sat, Jul 07, 2012 at 10:11:22AM -0700, Kees Cook wrote:
> While very unlikely, it is possible for arch_get_random_long() to fail
> in the middle of the loop in xfer_secondary_pool(), which would mean
> that the loop could stop with only part of u.hwrand populated, leading
> to mix_pool_bytes() injecting uninitialized or already injected bytes
> instead of fresh bytes. This changes the mix_pool_bytes() call to only
> inject the successfully gathered bytes.

I don't believe there is a major problem with injecting uninitialized
or even known bytes into the pool; worst case we're wastiing a tiny
amount of CPU in this unlikely case (versus the CPU costs of doing the
multiplication each time).  Not that I think really matters one way or
the other... 

Is there a reason why you're particularly concerned about what might
happen in the case where arch_get_random_long() fails mid-loop (which
can happen if RDRAND returns an error for whatever reason, granted)?

Regards,

						- Ted

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] random: only use gathered bytes from arch_get_random_long
  2012-07-07 18:23     ` Theodore Ts'o
@ 2012-07-07 23:20       ` Kees Cook
  0 siblings, 0 replies; 24+ messages in thread
From: Kees Cook @ 2012-07-07 23:20 UTC (permalink / raw)
  To: Theodore Ts'o, Kees Cook, Linux Kernel Developers List,
	ewust, zakir, nadiah, jhalderm, stable

On Sat, Jul 07, 2012 at 02:23:16PM -0400, Theodore Ts'o wrote:
> On Sat, Jul 07, 2012 at 10:11:22AM -0700, Kees Cook wrote:
> > While very unlikely, it is possible for arch_get_random_long() to fail
> > in the middle of the loop in xfer_secondary_pool(), which would mean
> > that the loop could stop with only part of u.hwrand populated, leading
> > to mix_pool_bytes() injecting uninitialized or already injected bytes
> > instead of fresh bytes. This changes the mix_pool_bytes() call to only
> > inject the successfully gathered bytes.
> 
> I don't believe there is a major problem with injecting uninitialized
> or even known bytes into the pool; worst case we're wastiing a tiny
> amount of CPU in this unlikely case (versus the CPU costs of doing the
> multiplication each time).  Not that I think really matters one way or
> the other... 
> 
> Is there a reason why you're particularly concerned about what might
> happen in the case where arch_get_random_long() fails mid-loop (which
> can happen if RDRAND returns an error for whatever reason, granted)?

Not really, but it seems like poor form to try to mix in data that wasn't
actually what you were expecting. I don't exactly see a problem with what
you've already got, but it seems like it's better to not have the bug at
all.

-Kees

-- 
Kees Cook
Chrome OS Security

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool
  2012-07-06 22:44 ` [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool Theodore Ts'o
  2012-07-07 17:11   ` [PATCH] random: only use gathered bytes from arch_get_random_long Kees Cook
@ 2012-07-08  1:06   ` Ben Hutchings
  2012-07-08  1:41     ` Theodore Ts'o
  1 sibling, 1 reply; 24+ messages in thread
From: Ben Hutchings @ 2012-07-08  1:06 UTC (permalink / raw)
  To: Theodore Ts'o
  Cc: Linux Kernel Developers List, ewust, zakir, nadiah, jhalderm, stable

[-- Attachment #1: Type: text/plain, Size: 1119 bytes --]

On Fri, 2012-07-06 at 18:44 -0400, Theodore Ts'o wrote:
> If the CPU supports a hardware random number generator, use it in
> xfer_secondary_pool(), where it will significantly improve things and
> where we can afford it.
> 
> Also, remove the use of the arch-specific rng in
> add_timer_randomness(), since the call is significantly slower than
> get_cycles(), and we're much better off using it in
> xfer_secondary_pool() anyway.
[...]
> @@ -838,7 +834,11 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
>   */
>  static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
>  {
> -	__u32 tmp[OUTPUT_POOL_WORDS];
> +	union {
> +		__u32	tmp[OUTPUT_POOL_WORDS];
> +		long	hwrand[4];
> +	} u;
> +	int	i;
[...]
> +	for (i = 0; i < 4; i++)
> +		if (arch_get_random_long(&u.hwrand[i]))
> +			break;
> +	if (i)
> +		mix_pool_bytes(r, &u.hwrand, sizeof(u.hwrand), 0);
[...]

Surely the number of random bytes being added is i * sizeof(long), not
sizeof(u.hwrand)?

Ben.

-- 
Ben Hutchings
Life would be so much easier if we could look at the source code.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool
  2012-07-08  1:06   ` [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool Ben Hutchings
@ 2012-07-08  1:41     ` Theodore Ts'o
  2012-07-08  2:06       ` Ben Hutchings
  0 siblings, 1 reply; 24+ messages in thread
From: Theodore Ts'o @ 2012-07-08  1:41 UTC (permalink / raw)
  To: Ben Hutchings
  Cc: Linux Kernel Developers List, ewust, zakir, nadiah, jhalderm, stable

On Sun, Jul 08, 2012 at 02:06:46AM +0100, Ben Hutchings wrote:
> 
> Surely the number of random bytes being added is i * sizeof(long), not
> sizeof(u.hwrand)?
> 

Meh; Kees Cook has made the same observation.  Basically, in the
unlikely case where RDRAND fails, we'll end up mixing in stack
garbage.  It's not a security vulnerability, since the contents of the
entropy pool never gets exposed.  In fact, one could argue that mixing
in some unknown garbage from the kernel stack might actually help a
little; but it can't hurt.

					- Ted

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 02/12] random: make 'add_interrupt_randomness()' do something sane
  2012-07-06 22:44 ` [PATCH 02/12] random: make 'add_interrupt_randomness()' do something sane Theodore Ts'o
@ 2012-07-08  2:01   ` Ben Hutchings
  0 siblings, 0 replies; 24+ messages in thread
From: Ben Hutchings @ 2012-07-08  2:01 UTC (permalink / raw)
  To: Theodore Ts'o
  Cc: Linux Kernel Developers List, ewust, zakir, nadiah, jhalderm,
	Linus Torvalds, stable

[-- Attachment #1: Type: text/plain, Size: 1519 bytes --]

On Fri, 2012-07-06 at 18:44 -0400, Theodore Ts'o wrote:
> We've been moving away from add_interrupt_randomness() for various
> reasons: it's too expensive to do on every interrupt, and flooding the
> CPU with interrupts could theoretically cause bogus floods of entropy
> from a somewhat externally controllable source.
> 
> This solves both problems by limiting the actual randomness addition
> to just once a second or after 128 interrupts, whicever comes first.

Seems to be once per 64 interrupts.  add_interrupt_randomness() calls
fast_mix() with nbytes = 20, so it increments fast_pool->count by 20.
add_interrupt_randomness() returns early if (fast_pool->count & 255),
and 64 * 20 == 0x500.

[...]
> +static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
> +{
> +       const char      *bytes = in;
> +       __u32           w;
> +       unsigned        i = f->count;
> +       unsigned        input_rotate = f->rotate;
> +
> +       while (nbytes--) {
> +               w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^
> +                       f->pool[(i + 1) & 3];
> +               f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7];
> +               input_rotate += (i++ & 3) ? 7 : 14;
> +       }
> +       f->count = i;
> +       f->rotate = input_rotate;
> +}
[...]

This seems like a comparatively expensive operation to add to every
interrupt. :-/

Ben.

-- 
Ben Hutchings
Life would be so much easier if we could look at the source code.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool
  2012-07-08  1:41     ` Theodore Ts'o
@ 2012-07-08  2:06       ` Ben Hutchings
  0 siblings, 0 replies; 24+ messages in thread
From: Ben Hutchings @ 2012-07-08  2:06 UTC (permalink / raw)
  To: Theodore Ts'o
  Cc: Linux Kernel Developers List, ewust, zakir, nadiah, jhalderm, stable

[-- Attachment #1: Type: text/plain, Size: 922 bytes --]

On Sat, 2012-07-07 at 21:41 -0400, Theodore Ts'o wrote:
> On Sun, Jul 08, 2012 at 02:06:46AM +0100, Ben Hutchings wrote:
> > 
> > Surely the number of random bytes being added is i * sizeof(long), not
> > sizeof(u.hwrand)?
> > 
> 
> Meh; Kees Cook has made the same observation.  Basically, in the
> unlikely case where RDRAND fails, we'll end up mixing in stack
> garbage.  It's not a security vulnerability, since the contents of the
> entropy pool never gets exposed.  In fact, one could argue that mixing
> in some unknown garbage from the kernel stack might actually help a
> little; but it can't hurt.

Sorry, I realised after reading further that there's no entropy being
credited.  However, I expect that kmemcheck will complain unless you
limit the used length or call kmemcheck_mark_initialized().

Ben.

-- 
Ben Hutchings
Life would be so much easier if we could look at the source code.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 828 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2012-07-08  2:06 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-06 22:44 [PATCH 00/12] /dev/random fixups Theodore Ts'o
2012-07-06 22:44 ` [PATCH 01/12] random: fix up sparse warnings Theodore Ts'o
2012-07-06 22:44 ` [PATCH 02/12] random: make 'add_interrupt_randomness()' do something sane Theodore Ts'o
2012-07-08  2:01   ` Ben Hutchings
2012-07-06 22:44 ` [PATCH 03/12] random: use lockless techniques in the interrupt path Theodore Ts'o
2012-07-06 22:44 ` [PATCH 04/12] random: create add_device_randomness() interface Theodore Ts'o
2012-07-06 22:44 ` [PATCH 05/12] usb: feed USB device information to the /dev/random driver Theodore Ts'o
2012-07-06 23:02   ` Jonathan Nieder
2012-07-06 23:18     ` Greg KH
2012-07-06 23:26     ` Theodore Ts'o
2012-07-07  1:08       ` Jonathan Nieder
2012-07-06 22:44 ` [PATCH 06/12] net: feed /dev/random with the MAC address when registering a device Theodore Ts'o
2012-07-06 22:44 ` [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool Theodore Ts'o
2012-07-07 17:11   ` [PATCH] random: only use gathered bytes from arch_get_random_long Kees Cook
2012-07-07 18:23     ` Theodore Ts'o
2012-07-07 23:20       ` Kees Cook
2012-07-08  1:06   ` [PATCH 07/12] random: use the arch-specific rng in xfer_secondary_pool Ben Hutchings
2012-07-08  1:41     ` Theodore Ts'o
2012-07-08  2:06       ` Ben Hutchings
2012-07-06 22:45 ` [PATCH 08/12] random: add new get_random_bytes_arch() function Theodore Ts'o
2012-07-06 22:45 ` [PATCH 09/12] random: add tracepoints for easier debugging and verification Theodore Ts'o
2012-07-06 22:45 ` [PATCH 10/12] MAINTAINERS: Theodore Ts'o is taking over the random driver Theodore Ts'o
2012-07-06 22:45 ` [PATCH 11/12] rtc: wm831x: Feed the write counter into device_add_randomness() Theodore Ts'o
2012-07-06 22:45 ` [PATCH 12/12] mfd: wm831x: Feed the device UUID " Theodore Ts'o

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.