]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Aug 2012 02:07:42 +0000 (19:07 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Aug 2012 02:07:42 +0000 (19:07 -0700)
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
  ...

39 files changed:
Documentation/feature-removal-schedule.txt
MAINTAINERS
arch/arm/mach-omap1/board-palmz71.c
arch/arm/mach-pxa/lubbock.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-pxa/trizeps4.c
arch/ia64/kernel/irq_ia64.c
arch/sparc/kernel/ldc.c
arch/um/drivers/line.c
arch/um/drivers/mconsole_kern.c
arch/um/drivers/port_kern.c
arch/um/drivers/random.c
arch/um/drivers/xterm_kern.c
arch/um/kernel/sigio.c
drivers/block/xen-blkfront.c
drivers/char/random.c
drivers/crypto/n2_core.c
drivers/firmware/dmi_scan.c
drivers/hv/vmbus_drv.c
drivers/i2c/busses/i2c-pmcmsp.c
drivers/input/serio/hp_sdc.c
drivers/mfd/ab3100-core.c
drivers/mfd/tps65010.c
drivers/mfd/wm831x-otp.c
drivers/power/pda_power.c
drivers/rtc/rtc-wm831x.c
drivers/tty/serial/uartlite.c
drivers/usb/core/hub.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/otg/isp1301_omap.c
include/linux/interrupt.h
include/linux/irqdesc.h
include/linux/random.h
include/trace/events/random.h [new file with mode: 0644]
kernel/irq/handle.c
kernel/irq/manage.c
net/core/dev.c
net/core/rtnetlink.c

index 09b132dd062d29fec269f5e18406e0f7f3a196b7..24fec7603e5e1dfa8b3e4226ffc889ed1709a33e 100644 (file)
@@ -70,20 +70,6 @@ Who: Luis R. Rodriguez <lrodriguez@atheros.com>
 
 ---------------------------
 
-What:  IRQF_SAMPLE_RANDOM
-Check: IRQF_SAMPLE_RANDOM
-When:  July 2009
-
-Why:   Many of IRQF_SAMPLE_RANDOM users are technically bogus as entropy
-       sources in the kernel's current entropy model. To resolve this, every
-       input point to the kernel's entropy pool needs to better document the
-       type of entropy source it actually is. This will be replaced with
-       additional add_*_randomness functions in drivers/char/random.c
-
-Who:   Robin Getz <rgetz@blackfin.uclinux.org> & Matt Mackall <mpm@selenic.com>
-
----------------------------
-
 What:  The ieee80211_regdom module parameter
 When:  March 2010 / desktop catchup
 
index 5b44872b64ecf79162810e52602c9663364190e5..36ed8a14e8e28ec1e11b1823f985a3c375338200 100644 (file)
@@ -5682,7 +5682,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
 
index cc71a26723efb0937294bfe777b10aa9a59ed746..355980321c2d19f91ecb55c2dd5b7b1a9c7f67dd 100644 (file)
@@ -288,8 +288,7 @@ palmz71_gpio_setup(int early)
                }
                gpio_direction_input(PALMZ71_USBDETECT_GPIO);
                if (request_irq(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
-                               palmz71_powercable, IRQF_SAMPLE_RANDOM,
-                               "palmz71-cable", NULL))
+                               palmz71_powercable, 0, "palmz71-cable", NULL))
                        printk(KERN_ERR
                                        "IRQ request for power cable failed!\n");
                palmz71_powercable(gpio_to_irq(PALMZ71_USBDETECT_GPIO), NULL);
index 6bb3f47b1f14e7070cfeb5c3dbaff57949adac10..0ca0db787903ab104ef9c0f216148cc3c32acee6 100644 (file)
@@ -456,7 +456,7 @@ static int lubbock_mci_init(struct device *dev,
        init_timer(&mmc_timer);
        mmc_timer.data = (unsigned long) data;
        return request_irq(LUBBOCK_SD_IRQ, lubbock_detect_int,
-                       IRQF_SAMPLE_RANDOM, "lubbock-sd-detect", data);
+                          0, "lubbock-sd-detect", data);
 }
 
 static int lubbock_mci_get_ro(struct device *dev)
index 2db697cd2b4ecc9fcb3be872aa0f82cd276b0577..39561dcf65f2668aa585a710fd09cda64c6249e6 100644 (file)
@@ -633,9 +633,8 @@ static struct platform_device bq24022 = {
 static int magician_mci_init(struct device *dev,
                                irq_handler_t detect_irq, void *data)
 {
-       return request_irq(IRQ_MAGICIAN_SD, detect_irq,
-                               IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
-                               "mmc card detect", data);
+       return request_irq(IRQ_MAGICIAN_SD, detect_irq, IRQF_DISABLED,
+                          "mmc card detect", data);
 }
 
 static void magician_mci_exit(struct device *dev, void *data)
index 2b6ac00b2cd98ce24e3e5e34bf56d36698d54c87..166dd32cc1d359e9c8299ea7a07146438d944020 100644 (file)
@@ -332,8 +332,8 @@ static int trizeps4_mci_init(struct device *dev, irq_handler_t mci_detect_int,
        int err;
 
        err = request_irq(TRIZEPS4_MMC_IRQ, mci_detect_int,
-               IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_SAMPLE_RANDOM,
-               "MMC card detect", data);
+                         IRQF_DISABLED | IRQF_TRIGGER_RISING,
+                         "MMC card detect", data);
        if (err) {
                printk(KERN_ERR "trizeps4_mci_init: MMC/SD: can't request"
                                                "MMC card detect IRQ\n");
index 5c3e0888265a80a2fe75d48f6ed8177aeb3aad7f..1034884b77da428c59190f9841229fc3e3cb8f41 100644 (file)
@@ -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>
index 435e406fdec3893a24753494eea408434d6810c8..81d92fc9983b1c0244ab395b7dd81c6725d20d26 100644 (file)
@@ -1250,14 +1250,12 @@ int ldc_bind(struct ldc_channel *lp, const char *name)
        snprintf(lp->rx_irq_name, LDC_IRQ_NAME_MAX, "%s RX", name);
        snprintf(lp->tx_irq_name, LDC_IRQ_NAME_MAX, "%s TX", name);
 
-       err = request_irq(lp->cfg.rx_irq, ldc_rx,
-                         IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
+       err = request_irq(lp->cfg.rx_irq, ldc_rx, IRQF_DISABLED,
                          lp->rx_irq_name, lp);
        if (err)
                return err;
 
-       err = request_irq(lp->cfg.tx_irq, ldc_tx,
-                         IRQF_SAMPLE_RANDOM | IRQF_DISABLED,
+       err = request_irq(lp->cfg.tx_irq, ldc_tx, IRQF_DISABLED,
                          lp->tx_irq_name, lp);
        if (err) {
                free_irq(lp->cfg.rx_irq, lp);
index acfd0e0fd0c98cfcabe626581eea0a722c86b6ff..ac9d25c8dc0162d36be49cbbb5cca6e54d88a883 100644 (file)
@@ -362,18 +362,18 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
 int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
 {
        const struct line_driver *driver = line->driver;
-       int err = 0, flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM;
+       int err = 0;
 
        if (input)
                err = um_request_irq(driver->read_irq, fd, IRQ_READ,
-                                      line_interrupt, flags,
-                                      driver->read_irq_name, data);
+                                    line_interrupt, IRQF_SHARED,
+                                    driver->read_irq_name, data);
        if (err)
                return err;
        if (output)
                err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
-                                       line_write_interrupt, flags,
-                                       driver->write_irq_name, data);
+                                    line_write_interrupt, IRQF_SHARED,
+                                    driver->write_irq_name, data);
        return err;
 }
 
@@ -779,8 +779,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
                                   .stack       = stack });
 
        if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
-                          IRQF_SHARED | IRQF_SAMPLE_RANDOM,
-                          "winch", winch) < 0) {
+                          IRQF_SHARED, "winch", winch) < 0) {
                printk(KERN_ERR "register_winch_irq - failed to register "
                       "IRQ\n");
                goto out_free;
index 43b39d61b538698229a23f654b7fb44a335187b3..664a60e8dfb442fe2cb75c1ed5ba388a7bdb42b0 100644 (file)
@@ -774,8 +774,7 @@ static int __init mconsole_init(void)
        register_reboot_notifier(&reboot_notifier);
 
        err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt,
-                            IRQF_SHARED | IRQF_SAMPLE_RANDOM,
-                            "mconsole", (void *)sock);
+                            IRQF_SHARED, "mconsole", (void *)sock);
        if (err) {
                printk(KERN_ERR "Failed to get IRQ for management console\n");
                goto out;
index 11866ffd45a988c24da3b38c07d806f2f5f2e1c5..1d83d50236e17a6a56e122aad6763b70b9222f9d 100644 (file)
@@ -100,8 +100,7 @@ static int port_accept(struct port_list *port)
                  .port         = port });
 
        if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
-                         IRQF_SHARED | IRQF_SAMPLE_RANDOM,
-                         "telnetd", conn)) {
+                         IRQF_SHARED, "telnetd", conn)) {
                printk(KERN_ERR "port_accept : failed to get IRQ for "
                       "telnetd\n");
                goto out_free;
@@ -184,8 +183,7 @@ void *port_data(int port_num)
        }
 
        if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
-                         IRQF_SHARED | IRQF_SAMPLE_RANDOM,
-                         "port", port)) {
+                         IRQF_SHARED, "port", port)) {
                printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num);
                goto out_close;
        }
index b25296e6218ade5fdeee1d3dff4f369bce5accbe..e32c6aa6396fa2df733b807b9252fa9acd755281 100644 (file)
@@ -131,8 +131,7 @@ static int __init rng_init (void)
        random_fd = err;
 
        err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
-                            IRQF_SAMPLE_RANDOM, "random",
-                            NULL);
+                            0, "random", NULL);
        if (err)
                goto err_out_cleanup_hw;
 
index b68bbe269e018cb00154781eec3706060e1b1c8d..e3031e69445d133d94a0e335dfd485bd04c17a4b 100644 (file)
@@ -50,8 +50,7 @@ int xterm_fd(int socket, int *pid_out)
        init_completion(&data->ready);
 
        err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt,
-                            IRQF_SHARED | IRQF_SAMPLE_RANDOM,
-                            "xterm", data);
+                            IRQF_SHARED, "xterm", data);
        if (err) {
                printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
                       "err = %d\n",  err);
index 2a1639255763973eaed54dfda4d20090a6e3bf5d..c88211139a5160ba5b18fa3117445e2b5f351423 100644 (file)
@@ -25,8 +25,7 @@ int write_sigio_irq(int fd)
        int err;
 
        err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
-                            IRQF_SAMPLE_RANDOM, "write sigio",
-                            NULL);
+                            0, "write sigio", NULL);
        if (err) {
                printk(KERN_ERR "write_sigio_irq : um_request_irq failed, "
                       "err = %d\n", err);
index e4fb3374dcd2aaa6d0f834cd9394564a3c022a38..2c2d2e5c15974c30755fd61715a189029dff7cd6 100644 (file)
@@ -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");
index 4ec04a754733baed5dd8595256a9c7998965d323..b86eae9b77dfaeb04dd2d4efefd6ebc01b9e0a93 100644 (file)
  * 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
 #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>
 #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
  */
 #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;
index 67b97c5fd85978bb09d4c9ab08ebe3afa86ff695..a8bd0310f8fec7fe5f8f7bceaf1987f7f38bd8dc 100644 (file)
@@ -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];
index 153980be4ee64462f12a97563c0143fc59b3eb82..b298158cb9224dd24eb65c5c00d2733b5d6cfc98 100644 (file)
@@ -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;
 }
index a220e5746d67df8922f7421b2ee0b174d6ae949b..4748086eaaf26ad41bd3b2fb0c7e40be4a34e054 100644 (file)
@@ -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",
index 07b7447ecbc9102c7721e27727ab7d25223f35d8..3d71395ae1f763d47ea11f33ba55eeab6ef7c174 100644 (file)
@@ -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.
index 09a089996ded673788e8302b7854e2a4669960d8..d7a7e54f64651227ca893f20ba729b72bb2c6d2d 100644 (file)
@@ -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;
 
index 4276aab4f1963bcc34eaceb94c5018e345b72a82..78fca2902c8da38fd07660e381e8ed55c0d78c2d 100644 (file)
@@ -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)
index 93d5fdf020c7eaa90dbf4d1eee41de216873d78e..da2691f22e114390f3f40817473f24a12c302f8f 100644 (file)
@@ -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);
index f742745ff354ec2bc485d533805f02340a11d2fd..b90f3e06b6c957f6a73aa87e0eb9bbec2f38fa58 100644 (file)
@@ -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;
 }
 
index 6a1ca735e93582b062d5b5e3e61d451427bef279..7312f2651647fbb97e64caa56fe03e778f2508a0 100644 (file)
 
 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;
index 59c6245e0421f21a70548108a2607ebdaa4bbd33..ea5c6f857ca5db35ebbfd3c581b0d5e7e32050d4 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/mfd/wm831x/core.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
-
+#include <linux/random.h>
 
 /*
  * R16416 (0x4020) - RTC Write Counter
@@ -96,6 +96,26 @@ struct wm831x_rtc {
        unsigned int alarm_enabled:1;
 };
 
+static void wm831x_rtc_add_randomness(struct wm831x *wm831x)
+{
+       int ret;
+       u16 reg;
+
+       /*
+        * The write counter contains a pseudo-random number which is
+        * regenerated every time we set the RTC so it should be a
+        * useful per-system source of entropy.
+        */
+       ret = wm831x_reg_read(wm831x, WM831X_RTC_WRITE_COUNTER);
+       if (ret >= 0) {
+               reg = ret;
+               add_device_randomness(&reg, sizeof(reg));
+       } else {
+               dev_warn(wm831x->dev, "Failed to read RTC write counter: %d\n",
+                        ret);
+       }
+}
+
 /*
  * Read current time and date in RTC
  */
@@ -431,6 +451,8 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
                        alm_irq, ret);
        }
 
+       wm831x_rtc_add_randomness(wm831x);
+
        return 0;
 
 err:
index 6cd414341d5ecebe293ecddc326d3be5832b88af..6579ffdd8e9ba3d2e4a6cf5a51031ebe60a092d0 100644 (file)
@@ -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;
 
index 821126eb81762ee2b57c971eec611c1e9a4e7ef6..128a804c42f406b6c6b1f32f57110ff6b0810b41 100644 (file)
@@ -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);
 
        /*
index 3d28fb976c7821898ea44fc4c8ac4656011d546a..9fd7886cfa9a7aac60035d7357e5ed00bfff40ff 100644 (file)
@@ -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;
index 53c093b941e5915302775b0916785fe24c7db866..907ad3ecb341b0c3dc285b478b3d34dc57b450d5 100644 (file)
@@ -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);
index 575fc815c932205a4255744f4288fd44790febde..7a88667742b663dc64f627560dfc5d34af32d0a7 100644 (file)
@@ -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) {
index e68a8e53bb59acf87c2dd07259f77ce491d5ec1e..c5f856a040b9252f116a3c58744176a2feba0b19 100644 (file)
@@ -42,7 +42,6 @@
  *
  * IRQF_DISABLED - keep irqs disabled when calling the action handler.
  *                 DEPRECATED. This flag is a NOOP and scheduled to be removed
- * IRQF_SAMPLE_RANDOM - irq is used to feed the random generator
  * IRQF_SHARED - allow sharing the irq among several devices
  * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
  * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
@@ -61,7 +60,6 @@
  *                resume time.
  */
 #define IRQF_DISABLED          0x00000020
-#define IRQF_SAMPLE_RANDOM     0x00000040
 #define IRQF_SHARED            0x00000080
 #define IRQF_PROBE_SHARED      0x00000100
 #define __IRQF_TIMER           0x00000200
index f1e2527006bd92f4780584b874c829bef49523e5..9a323d12de1c1700b10988013f38f6d8b1ca4615 100644 (file)
@@ -39,7 +39,6 @@ struct module;
  */
 struct irq_desc {
        struct irq_data         irq_data;
-       struct timer_rand_state *timer_rand_state;
        unsigned int __percpu   *kstat_irqs;
        irq_flow_handler_t      handle_irq;
 #ifdef CONFIG_IRQ_PREFLOW_FASTEOI
index 8f74538c96db5bd8615896593c2825628a29613c..ac621ce886ca13a600a879c0132ef2650113aa15 100644 (file)
@@ -48,13 +48,13 @@ struct rnd_state {
 
 #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);
-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);
+extern void get_random_bytes_arch(void *buf, int nbytes);
 void generate_random_uuid(unsigned char uuid_out[16]);
 
 #ifndef MODULE
diff --git a/include/trace/events/random.h b/include/trace/events/random.h
new file mode 100644 (file)
index 0000000..422df19
--- /dev/null
@@ -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>
index bdb1803255513ee8ee53c3683541348c6c9a4e0b..131ca176b4973c9b5f40ff8aa1ab471587ac71ae 100644 (file)
@@ -133,7 +133,7 @@ irqreturn_t
 handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
 {
        irqreturn_t retval = IRQ_NONE;
-       unsigned int random = 0, irq = desc->irq_data.irq;
+       unsigned int flags = 0, irq = desc->irq_data.irq;
 
        do {
                irqreturn_t res;
@@ -161,7 +161,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
 
                        /* Fall through to add to randomness */
                case IRQ_HANDLED:
-                       random |= action->flags;
+                       flags |= action->flags;
                        break;
 
                default:
@@ -172,8 +172,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
                action = action->next;
        } while (action);
 
-       if (random & IRQF_SAMPLE_RANDOM)
-               add_interrupt_randomness(irq);
+       add_interrupt_randomness(irq, flags);
 
        if (!noirqdebug)
                note_interrupt(irq, desc, retval);
index 814c9ef6bba14d7e212d082c659fe83f0f361ce8..0a8e8f059627dec4ee56bab79849e0f86372d3b5 100644 (file)
@@ -893,22 +893,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
                return -ENOSYS;
        if (!try_module_get(desc->owner))
                return -ENODEV;
-       /*
-        * 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);
-       }
 
        /*
         * Check whether the interrupt nests into another interrupt
@@ -1354,7 +1338,6 @@ EXPORT_SYMBOL(free_irq);
  *     Flags:
  *
  *     IRQF_SHARED             Interrupt is shared
- *     IRQF_SAMPLE_RANDOM      The interrupt can be used for entropy
  *     IRQF_TRIGGER_*          Specify active edge(s) or level
  *
  */
index 0ebaea16632fc348f6a48789831b737c7c51b707..c8569f826b717742d6614f5936f491f04ac65803 100644 (file)
@@ -1172,6 +1172,7 @@ static int __dev_open(struct net_device *dev)
                net_dmaengine_get();
                dev_set_rx_mode(dev);
                dev_activate(dev);
+               add_device_randomness(dev->dev_addr, dev->addr_len);
        }
 
        return ret;
@@ -4801,6 +4802,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);
@@ -5579,6 +5581,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);
index 5ff949dc954fa46d0f4787be2a3646205b69f408..2c5a0a06c4ce3053a4a6c6afa3437f3a47f2d08c 100644 (file)
@@ -1381,6 +1381,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]) {