diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-08-01 02:07:42 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-08-01 02:07:42 (GMT) |
commit | 3e9a97082fa639394e905e1fc4a0a7f719ca7644 (patch) | |
tree | 9985cfa26e0597128eae03a2ee7e4614efea571f /drivers | |
parent | 941c8726e4e737e74d418ccec3d8e7b946a65541 (diff) | |
parent | d2e7c96af1e54b507ae2a6a7dd2baf588417a7e5 (diff) | |
download | linux-3e9a97082fa639394e905e1fc4a0a7f719ca7644.tar.xz |
Merge tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random
Pull random subsystem patches from Ted Ts'o:
"This patch series contains a major revamp of how we collect entropy
from interrupts for /dev/random and /dev/urandom.
The goal is to addresses weaknesses discussed in the paper "Mining
your Ps and Qs: Detection of Widespread Weak Keys in Network Devices",
by Nadia Heninger, Zakir Durumeric, Eric Wustrow, J. Alex Halderman,
which will be published in the Proceedings of the 21st Usenix Security
Symposium, August 2012. (See https://factorable.net for more
information and an extended version of the paper.)"
Fix up trivial conflicts due to nearby changes in
drivers/{mfd/ab3100-core.c, usb/gadget/omap_udc.c}
* tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random: (33 commits)
random: mix in architectural randomness in extract_buf()
dmi: Feed DMI table to /dev/random driver
random: Add comment to random_initialize()
random: final removal of IRQF_SAMPLE_RANDOM
um: remove IRQF_SAMPLE_RANDOM which is now a no-op
sparc/ldc: remove IRQF_SAMPLE_RANDOM which is now a no-op
[ARM] pxa: remove IRQF_SAMPLE_RANDOM which is now a no-op
board-palmz71: remove IRQF_SAMPLE_RANDOM which is now a no-op
isp1301_omap: remove IRQF_SAMPLE_RANDOM which is now a no-op
pxa25x_udc: remove IRQF_SAMPLE_RANDOM which is now a no-op
omap_udc: remove IRQF_SAMPLE_RANDOM which is now a no-op
goku_udc: remove IRQF_SAMPLE_RANDOM which was commented out
uartlite: remove IRQF_SAMPLE_RANDOM which is now a no-op
drivers: hv: remove IRQF_SAMPLE_RANDOM which is now a no-op
xen-blkfront: remove IRQF_SAMPLE_RANDOM which is now a no-op
n2_crypto: remove IRQF_SAMPLE_RANDOM which is now a no-op
pda_power: remove IRQF_SAMPLE_RANDOM which is now a no-op
i2c-pmcmsp: remove IRQF_SAMPLE_RANDOM which is now a no-op
input/serio/hp_sdc.c: remove IRQF_SAMPLE_RANDOM which is now a no-op
mfd: remove IRQF_SAMPLE_RANDOM which is now a no-op
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/xen-blkfront.c | 5 | ||||
-rw-r--r-- | drivers/char/random.c | 355 | ||||
-rw-r--r-- | drivers/crypto/n2_core.c | 3 | ||||
-rw-r--r-- | drivers/firmware/dmi_scan.c | 3 | ||||
-rw-r--r-- | drivers/hv/vmbus_drv.c | 3 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-pmcmsp.c | 3 | ||||
-rw-r--r-- | drivers/input/serio/hp_sdc.c | 2 | ||||
-rw-r--r-- | drivers/mfd/ab3100-core.c | 4 | ||||
-rw-r--r-- | drivers/mfd/tps65010.c | 3 | ||||
-rw-r--r-- | drivers/mfd/wm831x-otp.c | 8 | ||||
-rw-r--r-- | drivers/power/pda_power.c | 6 | ||||
-rw-r--r-- | drivers/rtc/rtc-wm831x.c | 24 | ||||
-rw-r--r-- | drivers/tty/serial/uartlite.c | 3 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 9 | ||||
-rw-r--r-- | drivers/usb/gadget/goku_udc.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/pxa25x_udc.c | 12 | ||||
-rw-r--r-- | drivers/usb/otg/isp1301_omap.c | 1 |
17 files changed, 287 insertions, 159 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index e4fb337..2c2d2e5 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -888,9 +888,8 @@ static int setup_blkring(struct xenbus_device *dev, if (err) goto fail; - err = bind_evtchn_to_irqhandler(info->evtchn, - blkif_interrupt, - IRQF_SAMPLE_RANDOM, "blkif", info); + err = bind_evtchn_to_irqhandler(info->evtchn, blkif_interrupt, 0, + "blkif", info); if (err <= 0) { xenbus_dev_fatal(dev, err, "bind_evtchn_to_irqhandler failed"); diff --git a/drivers/char/random.c b/drivers/char/random.c index 4ec04a7..b86eae9 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -125,21 +125,26 @@ * 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); + * 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. * - * 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 +253,8 @@ #include <linux/percpu.h> #include <linux/cryptohash.h> #include <linux/fips.h> +#include <linux/ptrace.h> +#include <linux/kmemcheck.h> #ifdef CONFIG_GENERIC_HARDIRQS # include <linux/irq.h> @@ -256,8 +263,12 @@ #include <asm/processor.h> #include <asm/uaccess.h> #include <asm/irq.h> +#include <asm/irq_regs.h> #include <asm/io.h> +#define CREATE_TRACE_POINTS +#include <trace/events/random.h> + /* * Configuration information */ @@ -266,6 +277,8 @@ #define SEC_XFER_SIZE 512 #define EXTRACT_SIZE 10 +#define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long)) + /* * The minimum number of bits of entropy before we wake up a read on * /dev/random. Should be enough to do a significant reseed. @@ -420,8 +433,10 @@ struct entropy_store { /* read-write data: */ spinlock_t lock; unsigned add_ptr; + unsigned input_rotate; int entropy_count; - int input_rotate; + int entropy_total; + unsigned int initialized:1; __u8 last_data[EXTRACT_SIZE]; }; @@ -454,6 +469,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 @@ -464,29 +483,24 @@ static struct entropy_store nonblocking_pool = { * 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]) { - 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; 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--) { @@ -513,19 +527,61 @@ 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]; +} + +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); spin_unlock_irqrestore(&r->lock, flags); } -static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes) +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) { - mix_pool_bytes_extract(r, in, bytes, NULL); + 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; } /* @@ -533,30 +589,38 @@ static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes) */ 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; + if (r->entropy_total > 128) + 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); kill_fasync(&fasync, SIGIO, POLL_IN); } - spin_unlock_irqrestore(&r->lock, flags); } /********************************************************************* @@ -572,42 +636,24 @@ struct timer_rand_state { unsigned dont_count_entropy:1; }; -#ifndef CONFIG_GENERIC_HARDIRQS - -static struct timer_rand_state *irq_timer_state[NR_IRQS]; - -static struct timer_rand_state *get_timer_rand_state(unsigned int irq) -{ - return irq_timer_state[irq]; -} - -static void set_timer_rand_state(unsigned int irq, - struct timer_rand_state *state) -{ - irq_timer_state[irq] = state; -} - -#else - -static struct timer_rand_state *get_timer_rand_state(unsigned int irq) -{ - struct irq_desc *desc; - - desc = irq_to_desc(irq); - - return desc->timer_rand_state; -} - -static void set_timer_rand_state(unsigned int irq, - struct timer_rand_state *state) +/* + * 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) { - struct irq_desc *desc; + unsigned long time = get_cycles() ^ jiffies; - desc = irq_to_desc(irq); - - desc->timer_rand_state = state; + 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); } -#endif +EXPORT_SYMBOL(add_device_randomness); static struct timer_rand_state input_timer_state; @@ -637,13 +683,9 @@ 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)); + mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL); /* * Calculate number of bits of randomness we probably added. @@ -700,17 +742,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 & 1023) && + !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), NULL); + /* + * 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 @@ -742,7 +815,7 @@ 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]; + __u32 tmp[OUTPUT_POOL_WORDS]; if (r->pull && r->entropy_count < nbytes * 8 && r->entropy_count < r->poolinfo->POOLBITS) { @@ -761,7 +834,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); } } @@ -820,13 +893,19 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, static void extract_buf(struct entropy_store *r, __u8 *out) { int i; - __u32 hash[5], workspace[SHA_WORKSPACE_WORDS]; + union { + __u32 w[5]; + unsigned long l[LONGS(EXTRACT_SIZE)]; + } hash; + __u32 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); + sha_init(hash.w); + spin_lock_irqsave(&r->lock, flags); for (i = 0; i < r->poolinfo->poolwords; i += 16) - sha_transform(hash, (__u8 *)(r->pool + i), workspace); + sha_transform(hash.w, (__u8 *)(r->pool + i), workspace); /* * We mix the hash back into the pool to prevent backtracking @@ -837,13 +916,14 @@ 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.w, sizeof(hash.w), extract); + spin_unlock_irqrestore(&r->lock, flags); /* * To avoid duplicates, we atomically extract a portion of the * pool while mixing, and hash one final time. */ - sha_transform(hash, extract, workspace); + sha_transform(hash.w, extract, workspace); memset(extract, 0, sizeof(extract)); memset(workspace, 0, sizeof(workspace)); @@ -852,20 +932,32 @@ static void extract_buf(struct entropy_store *r, __u8 *out) * pattern, we fold it in half. Thus, we always feed back * twice as much data as we output. */ - hash[0] ^= hash[3]; - hash[1] ^= hash[4]; - hash[2] ^= rol32(hash[2], 16); - memcpy(out, hash, EXTRACT_SIZE); - memset(hash, 0, sizeof(hash)); + hash.w[0] ^= hash.w[3]; + hash.w[1] ^= hash.w[4]; + hash.w[2] ^= rol32(hash.w[2], 16); + + /* + * If we have a architectural hardware random number + * generator, mix that in, too. + */ + for (i = 0; i < LONGS(EXTRACT_SIZE); i++) { + unsigned long v; + if (!arch_get_random_long(&v)) + break; + hash.l[i] ^= v; + } + + memcpy(out, &hash, EXTRACT_SIZE); + memset(&hash, 0, sizeof(hash)); } 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; + trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); xfer_secondary_pool(r, nbytes); nbytes = account(r, nbytes, min, reserved); @@ -873,6 +965,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"); @@ -898,6 +992,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); @@ -931,17 +1026,35 @@ 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; + trace_get_random_bytes(nbytes, _RET_IP_); while (nbytes) { unsigned long v; int chunk = min(nbytes, (int)sizeof(unsigned long)); - + if (!arch_get_random_long(&v)) break; @@ -950,9 +1063,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 @@ -966,23 +1081,30 @@ 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; - 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)) + r->entropy_total = 0; + 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); } +/* + * Note that setup_arch() may call add_device_randomness() + * long before we get here. This allows seeding of the pools + * with some platform dependent data very early in the boot + * process. But it limits our options here. We must use + * statically allocated structures that already have all + * initializations complete at compile time. We should also + * take care not to overwrite the precious per platform data + * we were given. + */ static int rand_initialize(void) { init_std_data(&input_pool); @@ -992,24 +1114,6 @@ static int rand_initialize(void) } module_init(rand_initialize); -void rand_initialize_irq(int irq) -{ - struct timer_rand_state *state; - - state = get_timer_rand_state(irq); - - if (state) - return; - - /* - * If kzalloc returns null, we just won't use that entropy - * source. - */ - state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL); - if (state) - set_timer_rand_state(irq, state); -} - #ifdef CONFIG_BLOCK void rand_initialize_disk(struct gendisk *disk) { @@ -1117,7 +1221,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(); } @@ -1279,6 +1383,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 +1449,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; diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 67b97c5..a8bd031 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -1610,8 +1610,7 @@ static int spu_map_ino(struct platform_device *dev, struct spu_mdesc_info *ip, sprintf(p->irq_name, "%s-%d", irq_name, index); - return request_irq(p->irq, handler, IRQF_SAMPLE_RANDOM, - p->irq_name, p); + return request_irq(p->irq, handler, 0, p->irq_name, p); } static struct kmem_cache *queue_cache[2]; diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 153980b..b298158 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -6,6 +6,7 @@ #include <linux/dmi.h> #include <linux/efi.h> #include <linux/bootmem.h> +#include <linux/random.h> #include <asm/dmi.h> /* @@ -111,6 +112,8 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, dmi_table(buf, dmi_len, dmi_num, decode, NULL); + add_device_randomness(buf, dmi_len); + dmi_iounmap(buf, dmi_len); return 0; } diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index a220e57..4748086 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -545,8 +545,7 @@ static int vmbus_bus_init(int irq) if (ret) goto err_cleanup; - ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM, - driver_name, hv_acpi_dev); + ret = request_irq(irq, vmbus_isr, 0, driver_name, hv_acpi_dev); if (ret != 0) { pr_err("Unable to request IRQ %d\n", diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index 07b7447..3d71395 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c @@ -306,8 +306,7 @@ static int __devinit pmcmsptwi_probe(struct platform_device *pldev) pmcmsptwi_data.irq = platform_get_irq(pldev, 0); if (pmcmsptwi_data.irq) { rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt, - IRQF_SHARED | IRQF_SAMPLE_RANDOM, - pldev->name, &pmcmsptwi_data); + IRQF_SHARED, pldev->name, &pmcmsptwi_data); if (rc == 0) { /* * Enable 'DONE' interrupt only. diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index 09a0899..d7a7e54 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c @@ -878,7 +878,7 @@ static int __init hp_sdc_init(void) #endif errstr = "IRQ not available for"; - if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED|IRQF_SAMPLE_RANDOM, + if (request_irq(hp_sdc.irq, &hp_sdc_isr, IRQF_SHARED, "HP SDC", &hp_sdc)) goto err1; diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 4276aab..78fca29 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) @@ -936,8 +934,6 @@ static int __devinit ab3100_probe(struct i2c_client *client, IRQF_ONESHOT, "ab3100-core", ab3100); if (err) goto exit_no_irq; - /* This real unpredictable IRQ is of course sampled for entropy */ - rand_initialize_irq(client->irq); err = abx500_register_ops(&client->dev, &ab3100_ops); if (err) diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index 93d5fdf..da2691f 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c @@ -563,8 +563,7 @@ static int tps65010_probe(struct i2c_client *client, */ if (client->irq > 0) { status = request_irq(client->irq, tps65010_irq, - IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_FALLING, - DRIVER_NAME, tps); + IRQF_TRIGGER_FALLING, DRIVER_NAME, tps); if (status < 0) { dev_dbg(&client->dev, "can't get IRQ %d, err %d\n", client->irq, status); 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; } diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c index 6a1ca73..7312f26 100644 --- a/drivers/power/pda_power.c +++ b/drivers/power/pda_power.c @@ -24,11 +24,7 @@ static inline unsigned int get_irq_flags(struct resource *res) { - unsigned int flags = IRQF_SAMPLE_RANDOM | IRQF_SHARED; - - flags |= res->flags & IRQF_TRIGGER_MASK; - - return flags; + return IRQF_SHARED | (res->flags & IRQF_TRIGGER_MASK); } static struct device *dev; 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(®, 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: diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index 6cd4143..6579ffd 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -216,8 +216,7 @@ static int ulite_startup(struct uart_port *port) { int ret; - ret = request_irq(port->irq, ulite_isr, - IRQF_SHARED | IRQF_SAMPLE_RANDOM, "uartlite", port); + ret = request_irq(port->irq, ulite_isr, IRQF_SHARED, "uartlite", port); if (ret) return ret; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 821126e..128a804 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -25,6 +25,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> @@ -2181,6 +2182,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); /* diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 3d28fb9..9fd7886 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1836,7 +1836,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* init to known state, then setup irqs */ udc_reset(dev); udc_reinit (dev); - if (request_irq(pdev->irq, goku_irq, IRQF_SHARED/*|IRQF_SAMPLE_RANDOM*/, + if (request_irq(pdev->irq, goku_irq, IRQF_SHARED, driver_name, dev) != 0) { DBG(dev, "request interrupt %d failed\n", pdev->irq); retval = -EBUSY; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 53c093b..907ad3e 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -2201,19 +2201,15 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) #ifdef CONFIG_ARCH_LUBBOCK if (machine_is_lubbock()) { - retval = request_irq(LUBBOCK_USB_DISC_IRQ, - lubbock_vbus_irq, - IRQF_SAMPLE_RANDOM, - driver_name, dev); + retval = request_irq(LUBBOCK_USB_DISC_IRQ, lubbock_vbus_irq, + 0, driver_name, dev); if (retval != 0) { pr_err("%s: can't get irq %i, err %d\n", driver_name, LUBBOCK_USB_DISC_IRQ, retval); goto err_irq_lub; } - retval = request_irq(LUBBOCK_USB_IRQ, - lubbock_vbus_irq, - IRQF_SAMPLE_RANDOM, - driver_name, dev); + retval = request_irq(LUBBOCK_USB_IRQ, lubbock_vbus_irq, + 0, driver_name, dev); if (retval != 0) { pr_err("%s: can't get irq %i, err %d\n", driver_name, LUBBOCK_USB_IRQ, retval); diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index 575fc81..7a88667 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c @@ -1576,7 +1576,6 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) isp->irq_type = IRQF_TRIGGER_FALLING; } - isp->irq_type |= IRQF_SAMPLE_RANDOM; status = request_irq(i2c->irq, isp1301_irq, isp->irq_type, DRIVER_NAME, isp); if (status < 0) { |