diff options
author | Paul Gortmaker <paul.gortmaker@windriver.com> | 2012-08-14 19:22:35 -0400 |
---|---|---|
committer | Paul Gortmaker <paul.gortmaker@windriver.com> | 2012-08-14 19:22:35 -0400 |
commit | 2ebd0393483394d14f846864c4bdd8f151b507ff (patch) | |
tree | 26e5966c0a71fb193d18af951438d33cb75d319f | |
parent | 26a358ea045b8ef413b3616a14effe59481a32f5 (diff) | |
download | longterm-queue-2.6.34-2ebd0393483394d14f846864c4bdd8f151b507ff.tar.gz |
random: updates for better at-boot randomness
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
24 files changed, 2302 insertions, 1 deletions
diff --git a/queue/MAINTAINERS-Theodore-Ts-o-is-taking-over-the-random-.patch b/queue/MAINTAINERS-Theodore-Ts-o-is-taking-over-the-random-.patch new file mode 100644 index 0000000..17e2586 --- /dev/null +++ b/queue/MAINTAINERS-Theodore-Ts-o-is-taking-over-the-random-.patch @@ -0,0 +1,30 @@ +From c07e4d3643e5dbcc4214bec7ec052620355358e9 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o <tytso@mit.edu> +Date: Wed, 4 Jul 2012 11:32:48 -0400 +Subject: [PATCH] MAINTAINERS: Theodore Ts'o is taking over the random driver + +commit 330e0a01d54c2b8606c56816f99af6ebc58ec92c upstream. + +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> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/MAINTAINERS b/MAINTAINERS +index 52bec00..de13f3e 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -4644,7 +4644,7 @@ F: Documentation/blockdev/ramdisk.txt + F: drivers/block/brd.c + + RANDOM NUMBER DRIVER +-M: Matt Mackall <mpm@selenic.com> ++M: Theodore Ts'o" <tytso@mit.edu> + S: Maintained + F: drivers/char/random.c + +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/dmi-Feed-DMI-table-to-dev-random-driver.patch b/queue/dmi-Feed-DMI-table-to-dev-random-driver.patch new file mode 100644 index 0000000..34c5871 --- /dev/null +++ b/queue/dmi-Feed-DMI-table-to-dev-random-driver.patch @@ -0,0 +1,38 @@ +From f8f6fff8f12302c60bcbb5ee2d370fed30aadffd Mon Sep 17 00:00:00 2001 +From: Tony Luck <tony.luck@intel.com> +Date: Fri, 20 Jul 2012 13:15:20 -0700 +Subject: [PATCH] dmi: Feed DMI table to /dev/random driver + +commit d114a33387472555188f142ed8e98acdb8181c6d upstream. + +Send the entire DMI (SMBIOS) table to the /dev/random driver to +help seed its pools. + +Signed-off-by: Tony Luck <tony.luck@intel.com> +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c +index d464672..1816d92 100644 +--- a/drivers/firmware/dmi_scan.c ++++ b/drivers/firmware/dmi_scan.c +@@ -5,6 +5,7 @@ + #include <linux/dmi.h> + #include <linux/efi.h> + #include <linux/bootmem.h> ++#include <linux/random.h> + #include <asm/dmi.h> + + /* +@@ -110,6 +111,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; + } +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/drivers-char-random.c-fix-boot-id-uniqueness-race.patch b/queue/drivers-char-random.c-fix-boot-id-uniqueness-race.patch new file mode 100644 index 0000000..9a84de5 --- /dev/null +++ b/queue/drivers-char-random.c-fix-boot-id-uniqueness-race.patch @@ -0,0 +1,52 @@ +From 271cc0a5c648ce2161de4b98739dcdeef9639327 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Thu, 12 Apr 2012 12:49:12 -0700 +Subject: [PATCH] drivers/char/random.c: fix boot id uniqueness race + +commit 44e4360fa3384850d65dd36fb4e6e5f2f112709b upstream. + +/proc/sys/kernel/random/boot_id can be read concurrently by userspace +processes. If two (or more) user-space processes concurrently read +boot_id when sysctl_bootid is not yet assigned, a race can occur making +boot_id differ between the reads. Because the whole point of the boot id +is to be unique across a kernel execution, fix this by protecting this +operation with a spinlock. + +Given that this operation is not frequently used, hitting the spinlock +on each call should not be an issue. + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Cc: "Theodore Ts'o" <tytso@mit.edu> +Cc: Matt Mackall <mpm@selenic.com> +Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> +Cc: Greg Kroah-Hartman <greg@kroah.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index eda1a08..8bf21b1 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -1251,10 +1251,15 @@ static int proc_do_uuid(ctl_table *table, int write, + uuid = table->data; + if (!uuid) { + uuid = tmp_uuid; +- uuid[8] = 0; +- } +- if (uuid[8] == 0) + generate_random_uuid(uuid); ++ } else { ++ static DEFINE_SPINLOCK(bootid_spinlock); ++ ++ spin_lock(&bootid_spinlock); ++ if (!uuid[8]) ++ generate_random_uuid(uuid); ++ spin_unlock(&bootid_spinlock); ++ } + + sprintf(buf, "%pU", uuid); + +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/fix-typo-thinko-in-get_random_bytes.patch b/queue/fix-typo-thinko-in-get_random_bytes.patch new file mode 100644 index 0000000..18db392 --- /dev/null +++ b/queue/fix-typo-thinko-in-get_random_bytes.patch @@ -0,0 +1,34 @@ +From 2778ec8025fe0073af60af59ef8157bb9ae2c867 Mon Sep 17 00:00:00 2001 +From: "Luck, Tony" <tony.luck@intel.com> +Date: Wed, 16 Nov 2011 10:50:56 -0800 +Subject: [PATCH] fix typo/thinko in get_random_bytes() + +commit bd29e568a4cb6465f6e5ec7c1c1f3ae7d99cbec1 upstream. + +If there is an architecture-specific random number generator we use it +to acquire randomness one "long" at a time. We should put these random +words into consecutive words in the result buffer - not just overwrite +the first word again and again. + +Signed-off-by: Tony Luck <tony.luck@intel.com> +Acked-by: H. Peter Anvin <hpa@zytor.com> +Acked-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 2ae2f23..f017045 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -934,7 +934,7 @@ void get_random_bytes(void *buf, int nbytes) + if (!arch_get_random_long(&v)) + break; + +- memcpy(buf, &v, chunk); ++ memcpy(p, &v, chunk); + p += chunk; + nbytes -= chunk; + } +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/mfd-wm831x-Feed-the-device-UUID-into-device_add_rand.patch b/queue/mfd-wm831x-Feed-the-device-UUID-into-device_add_rand.patch new file mode 100644 index 0000000..9cb26fb --- /dev/null +++ b/queue/mfd-wm831x-Feed-the-device-UUID-into-device_add_rand.patch @@ -0,0 +1,51 @@ +From 326de4683b7464c250b8aae8edaf9265eda98eed Mon Sep 17 00:00:00 2001 +From: Mark Brown <broonie@opensource.wolfsonmicro.com> +Date: Thu, 5 Jul 2012 20:23:21 +0000 +Subject: [PATCH] mfd: wm831x: Feed the device UUID into + device_add_randomness() + +commit 27130f0cc3ab97560384da437e4621fc4e94f21c upstream. + +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> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +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.12.rc1.1.gbce1580 + diff --git a/queue/net-feed-dev-random-with-the-MAC-address-when-regist.patch b/queue/net-feed-dev-random-with-the-MAC-address-when-regist.patch new file mode 100644 index 0000000..0a7da85 --- /dev/null +++ b/queue/net-feed-dev-random-with-the-MAC-address-when-regist.patch @@ -0,0 +1,56 @@ +From 3547b3efb79cab37eb2a4768ab3567f64439559b Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o <tytso@mit.edu> +Date: Wed, 4 Jul 2012 21:23:25 -0400 +Subject: [PATCH] net: feed /dev/random with the MAC address when registering + a device + +commit 7bf2357524408b97fec58344caf7397f8140c3fd upstream. + +Cc: David Miller <davem@davemloft.net> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/net/core/dev.c b/net/core/dev.c +index bcd5f6e..7daff00 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1177,6 +1177,7 @@ static int __dev_open(struct net_device *dev) + * Wakeup transmit queue engine + */ + dev_activate(dev); ++ add_device_randomness(dev->dev_addr, dev->addr_len); + } + + return ret; +@@ -4492,6 +4493,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); +@@ -5141,6 +5143,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 31e85d3..835f38c 100644 +--- a/net/core/rtnetlink.c ++++ b/net/core/rtnetlink.c +@@ -974,6 +974,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.12.rc1.1.gbce1580 + diff --git a/queue/random-Add-comment-to-random_initialize.patch b/queue/random-Add-comment-to-random_initialize.patch new file mode 100644 index 0000000..c4a175b --- /dev/null +++ b/queue/random-Add-comment-to-random_initialize.patch @@ -0,0 +1,50 @@ +From 49d6f03641b2f46b9077aa68500ef599157c228d Mon Sep 17 00:00:00 2001 +From: Tony Luck <tony.luck@intel.com> +Date: Mon, 23 Jul 2012 09:47:57 -0700 +Subject: [PATCH] random: Add comment to random_initialize() + +commit cbc96b7594b5691d61eba2db8b2ea723645be9ca upstream. + +Many platforms have per-machine instance data (serial numbers, +asset tags, etc.) squirreled away in areas that are accessed +during early system bringup. Mixing this data into the random +pools has a very high value in providing better random data, +so we should allow (and even encourage) architecture code to +call add_device_randomness() from the setup_arch() paths. + +However, this limits our options for internal structure of +the random driver since random_initialize() is not called +until long after setup_arch(). + +Add a big fat comment to rand_initialize() spelling out +this requirement. + +Suggested-by: Theodore Ts'o <tytso@mit.edu> +Signed-off-by: Tony Luck <tony.luck@intel.com> +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index ee3d6d0..69eaacd 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -1088,6 +1088,16 @@ static void init_std_data(struct entropy_store *r) + 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); +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/random-Add-support-for-architectural-random-hooks.patch b/queue/random-Add-support-for-architectural-random-hooks.patch new file mode 100644 index 0000000..18e8c2f --- /dev/null +++ b/queue/random-Add-support-for-architectural-random-hooks.patch @@ -0,0 +1,97 @@ +From 1eeeef7a393d031c5a567d08a4925772fb9c399b Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" <hpa@zytor.com> +Date: Sun, 31 Jul 2011 13:54:50 -0700 +Subject: [PATCH] random: Add support for architectural random hooks + +commit 63d77173266c1791f1553e9e8ccea65dc87c4485 upstream. + +Add support for architecture-specific hooks into the kernel-directed +random number generator interfaces. This patchset does not use the +architecture random number generator interfaces for the +userspace-directed interfaces (/dev/random and /dev/urandom), thus +eliminating the need to distinguish between them based on a pool +pointer. + +Changes in version 3: +- Moved the hooks from extract_entropy() to get_random_bytes(). +- Changes the hooks to inlines. + +Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> +Cc: Fenghua Yu <fenghua.yu@intel.com> +Cc: Matt Mackall <mpm@selenic.com> +Cc: Herbert Xu <herbert@gondor.apana.org.au> +Cc: "Theodore Ts'o" <tytso@mit.edu> +[PG: .34 already had "unsigned int ret" in get_random_int, so the + diffstat here is slightly smaller than that of 63d7717. ] +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 1e07bbe..2ae2f23 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -925,7 +925,21 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, + */ + void get_random_bytes(void *buf, int nbytes) + { +- extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0); ++ char *p = buf; ++ ++ while (nbytes) { ++ unsigned long v; ++ int chunk = min(nbytes, (int)sizeof(unsigned long)); ++ ++ if (!arch_get_random_long(&v)) ++ break; ++ ++ memcpy(buf, &v, chunk); ++ p += chunk; ++ nbytes -= chunk; ++ } ++ ++ extract_entropy(&nonblocking_pool, p, nbytes, 0, 0); + } + EXPORT_SYMBOL(get_random_bytes); + +@@ -1309,9 +1323,14 @@ late_initcall(random_int_secret_init); + DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash); + unsigned int get_random_int(void) + { +- __u32 *hash = get_cpu_var(get_random_int_hash); ++ __u32 *hash; + unsigned int ret; + ++ if (arch_get_random_int(&ret)) ++ return ret; ++ ++ hash = get_cpu_var(get_random_int_hash); ++ + hash[0] += current->pid + jiffies + get_cycles(); + md5_transform(hash, random_int_secret); + ret = hash[0]; +diff --git a/include/linux/random.h b/include/linux/random.h +index 2948046..0bf2936 100644 +--- a/include/linux/random.h ++++ b/include/linux/random.h +@@ -63,6 +63,19 @@ unsigned long randomize_range(unsigned long start, unsigned long end, unsigned l + u32 random32(void); + void srandom32(u32 seed); + ++#ifdef CONFIG_ARCH_RANDOM ++# include <asm/archrandom.h> ++#else ++static inline int arch_get_random_long(unsigned long *v) ++{ ++ return 0; ++} ++static inline int arch_get_random_int(unsigned int *v) ++{ ++ return 0; ++} ++#endif ++ + #endif /* __KERNEL___ */ + + #endif /* _LINUX_RANDOM_H */ +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/random-Adjust-the-number-of-loops-when-initializing.patch b/queue/random-Adjust-the-number-of-loops-when-initializing.patch new file mode 100644 index 0000000..5e76167 --- /dev/null +++ b/queue/random-Adjust-the-number-of-loops-when-initializing.patch @@ -0,0 +1,34 @@ +From 30c603213737cdf39a268d19c1bc3f08c391702d Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" <hpa@linux.intel.com> +Date: Mon, 16 Jan 2012 11:23:29 -0800 +Subject: [PATCH] random: Adjust the number of loops when initializing + +commit 2dac8e54f988ab58525505d7ef982493374433c3 upstream. + +When we are initializing using arch_get_random_long() we only need to +loop enough times to touch all the bytes in the buffer; using +poolwords for that does twice the number of operations necessary on a +64-bit machine, since in the random number generator code "word" means +32 bits. + +Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> +Cc: "Theodore Ts'o" <tytso@mit.edu> +Link: http://lkml.kernel.org/r/1324589281-31931-1-git-send-email-tytso@mit.edu +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index c2ed1eb..eda1a08 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -968,7 +968,7 @@ static void init_std_data(struct entropy_store *r) + + now = ktime_get_real(); + mix_pool_bytes(r, &now, sizeof(now)); +- for (i = r->poolinfo->poolwords; i; i--) { ++ for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) { + if (!arch_get_random_long(&flags)) + break; + mix_pool_bytes(r, &flags, sizeof(flags)); +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/random-Use-arch-specific-RNG-to-initialize-the-entro.patch b/queue/random-Use-arch-specific-RNG-to-initialize-the-entro.patch new file mode 100644 index 0000000..c60457f --- /dev/null +++ b/queue/random-Use-arch-specific-RNG-to-initialize-the-entro.patch @@ -0,0 +1,46 @@ +From b964275438ff38b10373a2e335a2cdce8b50b785 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o <tytso@mit.edu> +Date: Thu, 22 Dec 2011 16:28:01 -0500 +Subject: [PATCH] random: Use arch-specific RNG to initialize the entropy + store + +commit 3e88bdff1c65145f7ba297ccec69c774afe4c785 upstream. + +If there is an architecture-specific random number generator (such as +RDRAND for Intel architectures), use it to initialize /dev/random's +entropy stores. Even in the worst case, if RDRAND is something like +AES(NSA_KEY, counter++), it won't hurt, and it will definitely help +against any other adversaries. + +Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> +Link: http://lkml.kernel.org/r/1324589281-31931-1-git-send-email-tytso@mit.edu +Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 4e9e6f9..c2ed1eb 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -958,6 +958,7 @@ EXPORT_SYMBOL(get_random_bytes); + */ + static void init_std_data(struct entropy_store *r) + { ++ int i; + ktime_t now; + unsigned long flags; + +@@ -967,6 +968,11 @@ static void init_std_data(struct entropy_store *r) + + now = ktime_get_real(); + mix_pool_bytes(r, &now, sizeof(now)); ++ for (i = r->poolinfo->poolwords; i; i--) { ++ if (!arch_get_random_long(&flags)) ++ break; ++ mix_pool_bytes(r, &flags, sizeof(flags)); ++ } + mix_pool_bytes(r, utsname(), sizeof(*(utsname()))); + } + +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/random-Use-arch_get_random_int-instead-of-cycle-coun.patch b/queue/random-Use-arch_get_random_int-instead-of-cycle-coun.patch new file mode 100644 index 0000000..859c104 --- /dev/null +++ b/queue/random-Use-arch_get_random_int-instead-of-cycle-coun.patch @@ -0,0 +1,66 @@ +From 154565f2565407088d65c2b282e3449dd386392d Mon Sep 17 00:00:00 2001 +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Thu, 22 Dec 2011 11:36:22 -0800 +Subject: [PATCH] random: Use arch_get_random_int instead of cycle counter if + avail + +commit cf833d0b9937874b50ef2867c4e8badfd64948ce upstream. + +We still don't use rdrand in /dev/random, which just seems stupid. We +accept the *cycle*counter* as a random input, but we don't accept +rdrand? That's just broken. + +Sure, people can do things in user space (write to /dev/random, use +rdrand in addition to /dev/random themselves etc etc), but that +*still* seems to be a particularly stupid reason for saying "we +shouldn't bother to try to do better in /dev/random". + +And even if somebody really doesn't trust rdrand as a source of random +bytes, it seems singularly stupid to trust the cycle counter *more*. + +So I'd suggest the attached patch. I'm not going to even bother +arguing that we should add more bits to the entropy estimate, because +that's not the point - I don't care if /dev/random fills up slowly or +not, I think it's just stupid to not use the bits we can get from +rdrand and mix them into the strong randomness pool. + +Link: http://lkml.kernel.org/r/CA%2B55aFwn59N1=m651QAyTy-1gO1noGbK18zwKDwvwqnravA84A@mail.gmail.com +Acked-by: "David S. Miller" <davem@davemloft.net> +Acked-by: "Theodore Ts'o" <tytso@mit.edu> +Acked-by: Herbert Xu <herbert@gondor.apana.org.au> +Cc: Matt Mackall <mpm@selenic.com> +Cc: Tony Luck <tony.luck@intel.com> +Cc: Eric Dumazet <eric.dumazet@gmail.com> +Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index f017045..4e9e6f9 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -617,8 +617,8 @@ static struct timer_rand_state input_timer_state; + static void add_timer_randomness(struct timer_rand_state *state, unsigned num) + { + struct { +- cycles_t cycles; + long jiffies; ++ unsigned cycles; + unsigned num; + } sample; + long delta, delta2, delta3; +@@ -630,7 +630,11 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) + goto out; + + sample.jiffies = jiffies; +- sample.cycles = get_cycles(); ++ ++ /* Use arch random value, fall back to cycles */ ++ if (!arch_get_random_int(&sample.cycles)) ++ sample.cycles = get_cycles(); ++ + sample.num = num; + mix_pool_bytes(&input_pool, &sample, sizeof(sample)); + +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/random-add-new-get_random_bytes_arch-function.patch b/queue/random-add-new-get_random_bytes_arch-function.patch new file mode 100644 index 0000000..0313143 --- /dev/null +++ b/queue/random-add-new-get_random_bytes_arch-function.patch @@ -0,0 +1,119 @@ +From 39bf57704faadf32d7d76043623e66b82d7657cd Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o <tytso@mit.edu> +Date: Thu, 5 Jul 2012 10:35:23 -0400 +Subject: [PATCH] random: add new get_random_bytes_arch() function + +commit c2557a303ab6712bb6e09447df828c557c710ac9 upstream. + +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> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 9e64e08..a81899b 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -1031,17 +1031,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; + +@@ -1050,9 +1067,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 7451093..5a376bc 100644 +--- a/include/linux/random.h ++++ b/include/linux/random.h +@@ -52,6 +52,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.12.rc1.1.gbce1580 + diff --git a/queue/random-add-tracepoints-for-easier-debugging-and-veri.patch b/queue/random-add-tracepoints-for-easier-debugging-and-veri.patch new file mode 100644 index 0000000..ba046dc --- /dev/null +++ b/queue/random-add-tracepoints-for-easier-debugging-and-veri.patch @@ -0,0 +1,245 @@ +From b4b746ce133e4620eacf57b62f24bb7e3de11560 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o <tytso@mit.edu> +Date: Wed, 4 Jul 2012 16:19:30 -0400 +Subject: [PATCH] random: add tracepoints for easier debugging and + verification + +commit 00ce1db1a634746040ace24c09a4e3a7949a3145 upstream. + +Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index a81899b..5efbe68 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -259,6 +259,9 @@ + #include <asm/irq_regs.h> + #include <asm/io.h> + ++#define CREATE_TRACE_POINTS ++#include <trace/events/random.h> ++ + /* + * Configuration information + */ +@@ -471,8 +474,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; +@@ -524,13 +527,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); + } + +@@ -578,6 +589,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; +@@ -592,6 +604,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); +@@ -964,6 +979,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); + +@@ -998,6 +1014,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); + +@@ -1055,6 +1072,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.12.rc1.1.gbce1580 + diff --git a/queue/random-create-add_device_randomness-interface.patch b/queue/random-create-add_device_randomness-interface.patch new file mode 100644 index 0000000..d79528e --- /dev/null +++ b/queue/random-create-add_device_randomness-interface.patch @@ -0,0 +1,88 @@ +From 41b05fb6874c60fa5be4d7cc8eed559935d46117 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Wed, 4 Jul 2012 11:16:01 -0400 +Subject: [PATCH] random: create add_device_randomness() interface + +commit a2080a67abe9e314f9e9c2cc3a4a176e8a8f8793 upstream. + +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> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 7d14492..f018abd 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -125,10 +125,19 @@ + * 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); + * ++ * 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. + * +@@ -639,6 +648,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 8a85602..7451093 100644 +--- a/include/linux/random.h ++++ b/include/linux/random.h +@@ -46,6 +46,7 @@ struct rand_pool_info { + + 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.12.rc1.1.gbce1580 + diff --git a/queue/random-make-add_interrupt_randomness-do-something-sa.patch b/queue/random-make-add_interrupt_randomness-do-something-sa.patch new file mode 100644 index 0000000..37495d7 --- /dev/null +++ b/queue/random-make-add_interrupt_randomness-do-something-sa.patch @@ -0,0 +1,282 @@ +From a3793014974976b09981f8f505020c3bbef03a71 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o <tytso@mit.edu> +Date: Mon, 2 Jul 2012 07:52:16 -0400 +Subject: [PATCH] random: make 'add_interrupt_randomness()' do something sane + +commit 775f4b297b780601e61787b766f306ed3e1d23eb upstream. + +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 64 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> +[PG: minor adjustment required since .34 doesn't have f9e4989eb8 + which renames "status" to "random" in kernel/irq/handle.c ] +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 8bf21b1..7a02eac 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -127,18 +127,14 @@ + * + * 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); + * + * 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. Disk interrupts are +- * a better measure, since the timing of the disk 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. + * + * All of these routines try to estimate how many bits of randomness a + * particular randomness source. They do this by keeping track of the +@@ -241,6 +237,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> +@@ -249,6 +246,7 @@ + #include <asm/processor.h> + #include <asm/uaccess.h> + #include <asm/irq.h> ++#include <asm/irq_regs.h> + #include <asm/io.h> + + /* +@@ -414,7 +412,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]; + }; + +@@ -447,6 +447,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 +@@ -460,9 +464,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; +@@ -521,6 +522,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 + */ +@@ -544,6 +575,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); +@@ -693,17 +730,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)); ++ /* ++ * 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 +@@ -964,6 +1032,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 4267a4d..2a193dc 100644 +--- a/drivers/mfd/ab3100-core.c ++++ b/drivers/mfd/ab3100-core.c +@@ -378,8 +378,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 0bf2936..8a85602 100644 +--- a/include/linux/random.h ++++ b/include/linux/random.h +@@ -48,7 +48,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 76d5a67..86bcf10 100644 +--- a/kernel/irq/handle.c ++++ b/kernel/irq/handle.c +@@ -368,7 +368,7 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action) + irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) + { + irqreturn_t ret, retval = IRQ_NONE; +- unsigned int status = 0; ++ unsigned int flags = 0; + + if (!(action->flags & IRQF_DISABLED)) + local_irq_enable_in_hardirq(); +@@ -411,7 +411,7 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) + + /* Fall through to add to randomness */ + case IRQ_HANDLED: +- status |= action->flags; ++ flags |= action->flags; + break; + + default: +@@ -422,8 +422,7 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) + action = action->next; + } while (action); + +- if (status & IRQF_SAMPLE_RANDOM) +- add_interrupt_randomness(irq); ++ add_interrupt_randomness(irq, flags); + local_irq_disable(); + + return retval; +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/random-mix-in-architectural-randomness-in-extract_bu.patch b/queue/random-mix-in-architectural-randomness-in-extract_bu.patch new file mode 100644 index 0000000..29dd57f --- /dev/null +++ b/queue/random-mix-in-architectural-randomness-in-extract_bu.patch @@ -0,0 +1,147 @@ +From 3948a2cbe5968506ce0e31f711c72a272fe097a8 Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" <hpa@linux.intel.com> +Date: Fri, 27 Jul 2012 22:26:08 -0400 +Subject: [PATCH] random: mix in architectural randomness in extract_buf() + +commit d2e7c96af1e54b507ae2a6a7dd2baf588417a7e5 upstream. + +Mix in any architectural randomness in extract_buf() instead of +xfer_secondary_buf(). This allows us to mix in more architectural +randomness, and it also makes xfer_secondary_buf() faster, moving a +tiny bit of additional CPU overhead to process which is extracting the +randomness. + +[ Commit description modified by tytso to remove an extended + advertisement for the RDRAND instruction. ] + +Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> +Acked-by: Ingo Molnar <mingo@kernel.org> +Cc: DJ Johnston <dj.johnston@intel.com> +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 5efbe68..5ad6b22 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -270,6 +270,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. +@@ -843,11 +845,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, + */ + static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) + { +- union { +- __u32 tmp[OUTPUT_POOL_WORDS]; +- long hwrand[4]; +- } u; +- int i; ++ __u32 tmp[OUTPUT_POOL_WORDS]; + + if (r->pull && r->entropy_count < nbytes * 8 && + r->entropy_count < r->poolinfo->POOLBITS) { +@@ -858,23 +856,17 @@ 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(u.tmp)); ++ bytes = min_t(int, bytes, sizeof(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, u.tmp, bytes, ++ bytes = extract_entropy(r->pull, tmp, bytes, + random_read_wakeup_thresh / 8, rsvd); +- mix_pool_bytes(r, u.tmp, bytes, NULL); ++ mix_pool_bytes(r, tmp, bytes, NULL); + credit_entropy_bits(r, bytes*8); + } +- kmemcheck_mark_initialized(&u.hwrand, sizeof(u.hwrand)); +- 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); + } + + /* +@@ -931,15 +923,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 +@@ -950,14 +946,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(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)); + +@@ -966,11 +962,23 @@ 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, +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/random-remove-rand_initialize_irq.patch b/queue/random-remove-rand_initialize_irq.patch new file mode 100644 index 0000000..2912ebb --- /dev/null +++ b/queue/random-remove-rand_initialize_irq.patch @@ -0,0 +1,181 @@ +From 19f2b5c93bce7d1e5379b5e9f760ae2b26a9b8cb Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o <tytso@mit.edu> +Date: Sat, 14 Jul 2012 20:27:52 -0400 +Subject: [PATCH] random: remove rand_initialize_irq() + +commit c5857ccf293968348e5eb4ebedc68074de3dcda6 upstream. + +With the new interrupt sampling system, we are no longer using the +timer_rand_state structure in the irq descriptor, so we can stop +initializing it now. + +[ Merged in fixes from Sedat to find some last missing references to + rand_initialize_irq() ] + +Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> +Signed-off-by: Sedat Dilek <sedat.dilek@gmail.com> +[PG: in .34 the irqdesc.h content is in irq.h instead.] +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c +index 6404793..73a3f5b 100644 +--- a/arch/ia64/kernel/irq_ia64.c ++++ b/arch/ia64/kernel/irq_ia64.c +@@ -23,7 +23,6 @@ + #include <linux/ioport.h> + #include <linux/kernel_stat.h> + #include <linux/ptrace.h> +-#include <linux/random.h> /* for rand_initialize_irq() */ + #include <linux/signal.h> + #include <linux/smp.h> + #include <linux/threads.h> +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 5ad6b22..ee3d6d0 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -629,43 +629,6 @@ 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) +-{ +- struct irq_desc *desc; +- +- desc = irq_to_desc(irq); +- +- desc->timer_rand_state = state; +-} +-#endif +- + /* + * Add device- or boot-specific data to the input and nonblocking + * pools to help initialize them to unique values. +@@ -1134,24 +1097,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) + { +diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c +index 2a193dc..5b7f5a90 100644 +--- a/drivers/mfd/ab3100-core.c ++++ b/drivers/mfd/ab3100-core.c +@@ -890,9 +890,6 @@ static int __init ab3100_probe(struct i2c_client *client, + + err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler, + IRQF_ONESHOT, "ab3100-core", ab3100); +- /* This real unpredictable IRQ is of course sampled for entropy */ +- rand_initialize_irq(client->irq); +- + if (err) + goto exit_no_irq; + +diff --git a/include/linux/irq.h b/include/linux/irq.h +index 707ab12..7c2e4bf 100644 +--- a/include/linux/irq.h ++++ b/include/linux/irq.h +@@ -174,7 +174,6 @@ struct irq_2_iommu; + */ + struct irq_desc { + unsigned int irq; +- struct timer_rand_state *timer_rand_state; + unsigned int *kstat_irqs; + #ifdef CONFIG_INTR_REMAP + struct irq_2_iommu *irq_2_iommu; +diff --git a/include/linux/random.h b/include/linux/random.h +index 5a376bc..1864957 100644 +--- a/include/linux/random.h ++++ b/include/linux/random.h +@@ -44,8 +44,6 @@ struct rand_pool_info { + + #ifdef __KERNEL__ + +-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); +diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c +index 46f10b1..9080985 100644 +--- a/kernel/irq/manage.c ++++ b/kernel/irq/manage.c +@@ -652,22 +652,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) + + if (desc->chip == &no_irq_chip) + return -ENOSYS; +- /* +- * Some drivers like serial.c use request_irq() heavily, +- * so we have to be careful not to interfere with a +- * running system. +- */ +- if (new->flags & IRQF_SAMPLE_RANDOM) { +- /* +- * This function might sleep, we want to call it first, +- * outside of the atomic block. +- * Yes, this might clear the entropy pool if the wrong +- * driver is attempted to be loaded, without actually +- * installing a new handler, but is this really a problem, +- * only the sysadmin is able to do this. +- */ +- rand_initialize_irq(irq); +- } + + /* Oneshot interrupts are not allowed with shared */ + if ((new->flags & IRQF_ONESHOT) && (new->flags & IRQF_SHARED)) +@@ -1040,7 +1024,6 @@ EXPORT_SYMBOL(free_irq); + * + * IRQF_SHARED Interrupt is shared + * IRQF_DISABLED Disable local interrupts while processing +- * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy + * IRQF_TRIGGER_* Specify active edge(s) or level + * + */ +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/random-simplify-fips-mode.patch b/queue/random-simplify-fips-mode.patch new file mode 100644 index 0000000..82d09b1 --- /dev/null +++ b/queue/random-simplify-fips-mode.patch @@ -0,0 +1,67 @@ +From 7d0dab18844ed26a119a9475da5c7cf8f28928da Mon Sep 17 00:00:00 2001 +From: Matt Mackall <mpm@selenic.com> +Date: Thu, 20 May 2010 19:55:01 +1000 +Subject: [PATCH] random: simplify fips mode + +commit e954bc91bdd4bb08b8325478c5004b24a23a3522 upstream. + +Rather than dynamically allocate 10 bytes, move it to static allocation. +This saves space and avoids the need for error checking. + +Signed-off-by: Matt Mackall <mpm@selenic.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +[PG: adding this simplifies required updates to random for .34 stable] +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index ccdadd9..1e07bbe 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -257,6 +257,7 @@ + #define INPUT_POOL_WORDS 128 + #define OUTPUT_POOL_WORDS 32 + #define SEC_XFER_SIZE 512 ++#define EXTRACT_SIZE 10 + + /* + * The minimum number of bits of entropy before we wake up a read on +@@ -414,7 +415,7 @@ struct entropy_store { + unsigned add_ptr; + int entropy_count; + int input_rotate; +- __u8 *last_data; ++ __u8 last_data[EXTRACT_SIZE]; + }; + + static __u32 input_pool_data[INPUT_POOL_WORDS]; +@@ -714,8 +715,6 @@ void add_disk_randomness(struct gendisk *disk) + } + #endif + +-#define EXTRACT_SIZE 10 +- + /********************************************************************* + * + * Entropy extraction routines +@@ -862,7 +861,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, + while (nbytes) { + extract_buf(r, tmp); + +- if (r->last_data) { ++ if (fips_enabled) { + spin_lock_irqsave(&r->lock, flags); + if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) + panic("Hardware RNG duplicated output!\n"); +@@ -951,9 +950,6 @@ static void init_std_data(struct entropy_store *r) + now = ktime_get_real(); + mix_pool_bytes(r, &now, sizeof(now)); + mix_pool_bytes(r, utsname(), sizeof(*(utsname()))); +- /* Enable continuous test in fips mode */ +- if (fips_enabled) +- r->last_data = kmalloc(EXTRACT_SIZE, GFP_KERNEL); + } + + static int rand_initialize(void) +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/random-use-lockless-techniques-in-the-interrupt-path.patch b/queue/random-use-lockless-techniques-in-the-interrupt-path.patch new file mode 100644 index 0000000..fc359b9 --- /dev/null +++ b/queue/random-use-lockless-techniques-in-the-interrupt-path.patch @@ -0,0 +1,242 @@ +From 00049db58596f5e8c99ae9992b2336e067e85586 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o <tytso@mit.edu> +Date: Wed, 4 Jul 2012 10:38:30 -0400 +Subject: [PATCH] random: use lockless techniques in the interrupt path + +commit 902c098a3663de3fa18639efbb71b6080f0bcd3c upstream. + +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> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index 7a02eac..7d14492 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -411,9 +411,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]; + }; +@@ -461,26 +461,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--) { +@@ -507,19 +505,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 { +@@ -557,23 +559,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; +@@ -586,7 +587,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); + } + + /********************************************************************* +@@ -673,7 +673,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. +@@ -757,7 +757,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 +@@ -822,7 +822,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); + } + } +@@ -883,9 +883,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); + +@@ -898,7 +900,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 +@@ -921,11 +924,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); +@@ -934,6 +936,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"); +@@ -1027,22 +1031,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) +@@ -1179,7 +1179,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.12.rc1.1.gbce1580 + diff --git a/queue/random-use-the-arch-specific-rng-in-xfer_secondary_p.patch b/queue/random-use-the-arch-specific-rng-in-xfer_secondary_p.patch new file mode 100644 index 0000000..254c233 --- /dev/null +++ b/queue/random-use-the-arch-specific-rng-in-xfer_secondary_p.patch @@ -0,0 +1,87 @@ +From 99920968490e6dfcb49071d55376cee2094a0f4f Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o <tytso@mit.edu> +Date: Thu, 5 Jul 2012 10:21:01 -0400 +Subject: [PATCH] random: use the arch-specific rng in xfer_secondary_pool + +commit e6d4947b12e8ad947add1032dd754803c6004824 upstream. + +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> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/char/random.c b/drivers/char/random.c +index f018abd..9e64e08 100644 +--- a/drivers/char/random.c ++++ b/drivers/char/random.c +@@ -247,6 +247,7 @@ + #include <linux/cryptohash.h> + #include <linux/fips.h> + #include <linux/ptrace.h> ++#include <linux/kmemcheck.h> + + #ifdef CONFIG_GENERIC_HARDIRQS + # include <linux/irq.h> +@@ -695,11 +696,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); + +@@ -831,7 +828,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) { +@@ -842,17 +843,23 @@ 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); + } ++ kmemcheck_mark_initialized(&u.hwrand, sizeof(u.hwrand)); ++ 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.12.rc1.1.gbce1580 + diff --git a/queue/rtc-wm831x-Feed-the-write-counter-into-device_add_ra.patch b/queue/rtc-wm831x-Feed-the-write-counter-into-device_add_ra.patch new file mode 100644 index 0000000..4b9a495 --- /dev/null +++ b/queue/rtc-wm831x-Feed-the-write-counter-into-device_add_ra.patch @@ -0,0 +1,72 @@ +From 116fcbfed6ef4520d2d0f75d5bf6719d705cd140 Mon Sep 17 00:00:00 2001 +From: Mark Brown <broonie@opensource.wolfsonmicro.com> +Date: Thu, 5 Jul 2012 20:19:17 +0000 +Subject: [PATCH] rtc: wm831x: Feed the write counter into + device_add_randomness() + +commit 9dccf55f4cb011a7552a8a2749a580662f5ed8ed upstream. + +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> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c +index b16cfe5..dce35ed 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 + */ +@@ -465,6 +485,8 @@ static int wm831x_rtc_probe(struct platform_device *pdev) + alm_irq, ret); + } + ++ wm831x_rtc_add_randomness(wm831x); ++ + return 0; + + err: +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/series b/queue/series index 70ca465..9882c82 100644 --- a/queue/series +++ b/queue/series @@ -18,6 +18,7 @@ security-fix-compile-error-in-commoncap.c.patch fcaps-clear-the-same-personality-flags-as-suid-when-.patch KEYS-Fix-a-NULL-pointer-deref-in-the-user-defined-ke.patch locks-fix-checking-of-fcntl_setlease-argument.patch + # content based on v2.6.32.47 additions USB-ftdi_sio-add-Calao-reference-board-support.patch USB-EHCI-Do-not-rely-on-PORT_SUSPEND-to-stop-USB-res.patch @@ -62,7 +63,6 @@ HID-usbhid-Add-support-for-SiGma-Micro-chip.patch hwmon-w83627ehf-Properly-report-thermal-diode-sensor.patch x25-Prevent-skb-overreads-when-checking-call-user-da.patch staging-quatech_usb2-Potential-lost-wakeup-scenario-.patch -# 32.47 USB-qcserial-add-device-ID-for-HP-un2430-Mobile-Broa.patch xhci-mem.c-Check-for-ring-first_seg-NULL.patch ipr-Always-initiate-hard-reset-in-kdump-kernel.patch @@ -146,3 +146,28 @@ USB-Fix-Corruption-issue-in-USB-ftdi-driver-ftdi_sio.patch usb-storage-Accept-8020i-protocol-commands-longer-th.patch USB-add-quirk-for-Logitech-C600-web-cam.patch USB-quirks-adding-more-quirky-webcams-to-avoid-squea.patch + +# updates relating to /dev/random -- based on 3.4.9 queue. +random-simplify-fips-mode.patch +random-Add-support-for-architectural-random-hooks.patch +x86-random-Architectural-inlines-to-get-random-integ.patch +fix-typo-thinko-in-get_random_bytes.patch +random-Use-arch_get_random_int-instead-of-cycle-coun.patch +random-Use-arch-specific-RNG-to-initialize-the-entro.patch +random-Adjust-the-number-of-loops-when-initializing.patch +drivers-char-random.c-fix-boot-id-uniqueness-race.patch +random-make-add_interrupt_randomness-do-something-sa.patch +random-use-lockless-techniques-in-the-interrupt-path.patch +random-create-add_device_randomness-interface.patch +random-use-the-arch-specific-rng-in-xfer_secondary_p.patch +random-add-new-get_random_bytes_arch-function.patch +random-add-tracepoints-for-easier-debugging-and-veri.patch +random-mix-in-architectural-randomness-in-extract_bu.patch +MAINTAINERS-Theodore-Ts-o-is-taking-over-the-random-.patch +usb-feed-USB-device-information-to-the-dev-random-dr.patch +net-feed-dev-random-with-the-MAC-address-when-regist.patch +random-remove-rand_initialize_irq.patch +random-Add-comment-to-random_initialize.patch +rtc-wm831x-Feed-the-write-counter-into-device_add_ra.patch +mfd-wm831x-Feed-the-device-UUID-into-device_add_rand.patch +dmi-Feed-DMI-table-to-dev-random-driver.patch diff --git a/queue/usb-feed-USB-device-information-to-the-dev-random-dr.patch b/queue/usb-feed-USB-device-information-to-the-dev-random-dr.patch new file mode 100644 index 0000000..a6e6842 --- /dev/null +++ b/queue/usb-feed-USB-device-information-to-the-dev-random-dr.patch @@ -0,0 +1,45 @@ +From 0f0ad59f7920983ba84dfec8aff05e1549a23b1d Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o <tytso@mit.edu> +Date: Wed, 4 Jul 2012 11:22:20 -0400 +Subject: [PATCH] usb: feed USB device information to the /dev/random driver + +commit b04b3156a20d395a7faa8eed98698d1e17a36000 upstream. + +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> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 40815d0..953269f 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -23,6 +23,7 @@ + #include <linux/mutex.h> + #include <linux/freezer.h> + #include <linux/pm_runtime.h> ++#include <linux/random.h> + + #include <asm/uaccess.h> + #include <asm/byteorder.h> +@@ -1827,6 +1828,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); + /* Register the device. The device driver is responsible + * for configuring the device and invoking the add-device +-- +1.7.12.rc1.1.gbce1580 + diff --git a/queue/x86-random-Architectural-inlines-to-get-random-integ.patch b/queue/x86-random-Architectural-inlines-to-get-random-integ.patch new file mode 100644 index 0000000..cc71f6a --- /dev/null +++ b/queue/x86-random-Architectural-inlines-to-get-random-integ.patch @@ -0,0 +1,147 @@ +From 909d022c74ab28bc87846215c7f6f31b8683ef98 Mon Sep 17 00:00:00 2001 +From: "H. Peter Anvin" <hpa@zytor.com> +Date: Sun, 31 Jul 2011 13:59:29 -0700 +Subject: [PATCH] x86, random: Architectural inlines to get random integers + with RDRAND + +commit 628c6246d47b85f5357298601df2444d7f4dd3fd upstream. + +Architectural inlines to get random ints and longs using the RDRAND +instruction. + +Intel has introduced a new RDRAND instruction, a Digital Random Number +Generator (DRNG), which is functionally an high bandwidth entropy +source, cryptographic whitener, and integrity monitor all built into +hardware. This enables RDRAND to be used directly, bypassing the +kernel random number pool. + +For technical documentation, see: + +http://software.intel.com/en-us/articles/download-the-latest-bull-mountain-software-implementation-guide/ + +In this patch, this is *only* used for the nonblocking random number +pool. RDRAND is a nonblocking source, similar to our /dev/urandom, +and is therefore not a direct replacement for /dev/random. The +architectural hooks presented in the previous patch only feed the +kernel internal users, which only use the nonblocking pool, and so +this is not a problem. + +Since this instruction is available in userspace, there is no reason +to have a /dev/hw_rng device driver for the purpose of feeding rngd. +This is especially so since RDRAND is a nonblocking source, and needs +additional whitening and reduction (see the above technical +documentation for details) in order to be of "pure entropy source" +quality. + +The CONFIG_EXPERT compile-time option can be used to disable this use +of RDRAND. + +Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> +Originally-by: Fenghua Yu <fenghua.yu@intel.com> +Cc: Matt Mackall <mpm@selenic.com> +Cc: Herbert Xu <herbert@gondor.apana.org.au> +Cc: "Theodore Ts'o" <tytso@mit.edu> +Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> + +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index b99909c..0a813f8 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -1460,6 +1460,15 @@ config ARCH_USES_PG_UNCACHED + def_bool y + depends on X86_PAT + ++config ARCH_RANDOM ++ def_bool y ++ prompt "x86 architectural random number generator" if EXPERT ++ ---help--- ++ Enable the x86 architectural RDRAND instruction ++ (Intel Bull Mountain technology) to generate random numbers. ++ If supported, this is a high bandwidth, cryptographically ++ secure hardware random number generator. ++ + config EFI + bool "EFI runtime service support" + depends on ACPI +diff --git a/arch/x86/include/asm/archrandom.h b/arch/x86/include/asm/archrandom.h +new file mode 100644 +index 0000000..b7b5bc0 +--- /dev/null ++++ b/arch/x86/include/asm/archrandom.h +@@ -0,0 +1,73 @@ ++/* ++ * This file is part of the Linux kernel. ++ * ++ * Copyright (c) 2011, Intel Corporation ++ * Authors: Fenghua Yu <fenghua.yu@intel.com>, ++ * H. Peter Anvin <hpa@linux.intel.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ */ ++ ++#ifndef ASM_X86_ARCHRANDOM_H ++#define ASM_X86_ARCHRANDOM_H ++ ++#include <asm/processor.h> ++#include <asm/cpufeature.h> ++#include <asm/alternative.h> ++#include <asm/nops.h> ++ ++#define RDRAND_RETRY_LOOPS 10 ++ ++#define RDRAND_INT ".byte 0x0f,0xc7,0xf0" ++#ifdef CONFIG_X86_64 ++# define RDRAND_LONG ".byte 0x48,0x0f,0xc7,0xf0" ++#else ++# define RDRAND_LONG RDRAND_INT ++#endif ++ ++#ifdef CONFIG_ARCH_RANDOM ++ ++#define GET_RANDOM(name, type, rdrand, nop) \ ++static inline int name(type *v) \ ++{ \ ++ int ok; \ ++ alternative_io("movl $0, %0\n\t" \ ++ nop, \ ++ "\n1: " rdrand "\n\t" \ ++ "jc 2f\n\t" \ ++ "decl %0\n\t" \ ++ "jnz 1b\n\t" \ ++ "2:", \ ++ X86_FEATURE_RDRAND, \ ++ ASM_OUTPUT2("=r" (ok), "=a" (*v)), \ ++ "0" (RDRAND_RETRY_LOOPS)); \ ++ return ok; \ ++} ++ ++#ifdef CONFIG_X86_64 ++ ++GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP5); ++GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP4); ++ ++#else ++ ++GET_RANDOM(arch_get_random_long, unsigned long, RDRAND_LONG, ASM_NOP3); ++GET_RANDOM(arch_get_random_int, unsigned int, RDRAND_INT, ASM_NOP3); ++ ++#endif /* CONFIG_X86_64 */ ++ ++#endif /* CONFIG_ARCH_RANDOM */ ++ ++#endif /* ASM_X86_ARCHRANDOM_H */ +-- +1.7.12.rc1.1.gbce1580 + |