Remove Andrew Morton's old email accounts
[safe/jmp/linux-2.6] / drivers / char / random.c
index e52f64c..6af435b 100644 (file)
 #include <linux/fs.h>
 #include <linux/genhd.h>
 #include <linux/interrupt.h>
+#include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/percpu.h>
 #include <linux/cryptohash.h>
@@ -370,6 +371,7 @@ static struct poolinfo {
  */
 static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
 static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
+static struct fasync_struct *fasync;
 
 #if 0
 static int debug;
@@ -395,7 +397,7 @@ module_param(debug, bool, 0644);
 
 struct entropy_store;
 struct entropy_store {
-       /* mostly-read data: */
+       /* read-only data: */
        struct poolinfo *poolinfo;
        __u32 *pool;
        const char *name;
@@ -403,9 +405,9 @@ struct entropy_store {
        struct entropy_store *pull;
 
        /* read-write data: */
-       spinlock_t lock ____cacheline_aligned_in_smp;
+       spinlock_t lock;
        unsigned add_ptr;
-       int entropy_count;
+       int entropy_count;      /* Must at no time exceed ->POOLBITS! */
        int input_rotate;
 };
 
@@ -439,25 +441,26 @@ static struct entropy_store nonblocking_pool = {
 };
 
 /*
- * This function adds a byte into the entropy "pool".  It does not
+ * This function adds bytes into the entropy "pool".  It does not
  * update the entropy estimate.  The caller should call
- * credit_entropy_store if this is appropriate.
+ * credit_entropy_bits if this is appropriate.
  *
  * The pool is stirred with a primitive polynomial of the appropriate
  * degree, and then twisted.  We twist by three bits at a time because
  * 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 __add_entropy_words(struct entropy_store *r, const __u32 *in,
-                               int nwords, __u32 out[16])
+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, add_ptr, tap1, tap2, tap3, tap4, tap5;
-       int new_rotate, input_rotate;
+       unsigned long i, j, tap1, tap2, tap3, tap4, tap5;
+       int input_rotate;
        int wordmask = r->poolinfo->poolwords - 1;
-       __u32 w, next_w;
+       const char *bytes = in;
+       __u32 w;
        unsigned long flags;
 
        /* Taps are constant, so we can load them without holding r->lock.  */
@@ -466,84 +469,79 @@ static void __add_entropy_words(struct entropy_store *r, const __u32 *in,
        tap3 = r->poolinfo->tap3;
        tap4 = r->poolinfo->tap4;
        tap5 = r->poolinfo->tap5;
-       next_w = *in++;
 
        spin_lock_irqsave(&r->lock, flags);
-       prefetch_range(r->pool, wordmask);
        input_rotate = r->input_rotate;
-       add_ptr = r->add_ptr;
+       i = r->add_ptr;
 
-       while (nwords--) {
-               w = rol32(next_w, input_rotate);
-               if (nwords > 0)
-                       next_w = *in++;
-               i = add_ptr = (add_ptr - 1) & wordmask;
-               /*
-                * Normally, we add 7 bits of rotation to the pool.
-                * At the beginning of the pool, add an extra 7 bits
-                * rotation, so that successive passes spread the
-                * input bits across the pool evenly.
-                */
-               new_rotate = input_rotate + 14;
-               if (i)
-                       new_rotate = input_rotate + 7;
-               input_rotate = new_rotate & 31;
+       /* mix one byte at a time to simplify size handling and churn faster */
+       while (nbytes--) {
+               w = rol32(*bytes++, input_rotate & 31);
+               i = (i - 1) & wordmask;
 
                /* XOR in the various taps */
+               w ^= r->pool[i];
                w ^= r->pool[(i + tap1) & wordmask];
                w ^= r->pool[(i + tap2) & wordmask];
                w ^= r->pool[(i + tap3) & wordmask];
                w ^= r->pool[(i + tap4) & wordmask];
                w ^= r->pool[(i + tap5) & wordmask];
-               w ^= r->pool[i];
+
+               /* Mix the result back in with a twist */
                r->pool[i] = (w >> 3) ^ twist_table[w & 7];
+
+               /*
+                * Normally, we add 7 bits of rotation to the pool.
+                * At the beginning of the pool, add an extra 7 bits
+                * rotation, so that successive passes spread the
+                * input bits across the pool evenly.
+                */
+               input_rotate += i ? 7 : 14;
        }
 
        r->input_rotate = input_rotate;
-       r->add_ptr = add_ptr;
+       r->add_ptr = i;
 
-       if (out) {
-               for (i = 0; i < 16; i++) {
-                       out[i] = r->pool[add_ptr];
-                       add_ptr = (add_ptr - 1) & wordmask;
-               }
-       }
+       if (out)
+               for (j = 0; j < 16; j++)
+                       ((__u32 *)out)[j] = r->pool[(i - j) & wordmask];
 
        spin_unlock_irqrestore(&r->lock, flags);
 }
 
-static inline void add_entropy_words(struct entropy_store *r, const __u32 *in,
-                                    int nwords)
+static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes)
 {
-       __add_entropy_words(r, in, nwords, NULL);
+       mix_pool_bytes_extract(r, in, bytes, NULL);
 }
 
 /*
  * Credit (or debit) the entropy store with n bits of entropy
  */
-static void credit_entropy_store(struct entropy_store *r, int nbits)
+static void credit_entropy_bits(struct entropy_store *r, int nbits)
 {
        unsigned long flags;
+       int entropy_count;
+
+       if (!nbits)
+               return;
 
        spin_lock_irqsave(&r->lock, flags);
 
-       if (r->entropy_count + nbits < 0) {
-               DEBUG_ENT("negative entropy/overflow (%d+%d)\n",
-                         r->entropy_count, nbits);
-               r->entropy_count = 0;
-       } else if (r->entropy_count + nbits > r->poolinfo->POOLBITS) {
-               r->entropy_count = r->poolinfo->POOLBITS;
-       } else {
-               r->entropy_count += nbits;
-               if (nbits)
-                       DEBUG_ENT("added %d entropy credits to %s\n",
-                                 nbits, r->name);
-       }
+       DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
+       entropy_count = 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;
 
        /* should we wake readers? */
-       if (r == &input_pool && r->entropy_count >= random_read_wakeup_thresh)
+       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);
 }
 
@@ -591,7 +589,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
        sample.jiffies = jiffies;
        sample.cycles = get_cycles();
        sample.num = num;
-       add_entropy_words(&input_pool, (u32 *)&sample, sizeof(sample)/4);
+       mix_pool_bytes(&input_pool, &sample, sizeof(sample));
 
        /*
         * Calculate number of bits of randomness we probably added.
@@ -625,8 +623,8 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
                 * Round down by 1 bit on general principles,
                 * and limit entropy entimate to 12 bits.
                 */
-               credit_entropy_store(&input_pool,
-                                    min_t(int, fls(delta>>1), 11));
+               credit_entropy_bits(&input_pool,
+                                   min_t(int, fls(delta>>1), 11));
        }
 out:
        preempt_enable();
@@ -663,10 +661,10 @@ void add_disk_randomness(struct gendisk *disk)
        if (!disk || !disk->random)
                return;
        /* first major is 1, so we get >= 0x200 here */
-       DEBUG_ENT("disk event %d:%d\n", disk->major, disk->first_minor);
+       DEBUG_ENT("disk event %d:%d\n",
+                 MAJOR(disk_devt(disk)), MINOR(disk_devt(disk)));
 
-       add_timer_randomness(disk->random,
-                            0x100 + MKDEV(disk->major, disk->first_minor));
+       add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
 }
 #endif
 
@@ -707,8 +705,8 @@ 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);
-               add_entropy_words(r, tmp, (bytes + 3) / 4);
-               credit_entropy_store(r, bytes*8);
+               mix_pool_bytes(r, tmp, bytes);
+               credit_entropy_bits(r, bytes*8);
        }
 }
 
@@ -750,8 +748,10 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
                else
                        r->entropy_count = reserved;
 
-               if (r->entropy_count < random_write_wakeup_thresh)
+               if (r->entropy_count < random_write_wakeup_thresh) {
                        wake_up_interruptible(&random_write_wait);
+                       kill_fasync(&fasync, SIGIO, POLL_OUT);
+               }
        }
 
        DEBUG_ENT("debiting %d entropy credits from %s%s\n",
@@ -765,7 +765,8 @@ 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 extract[16], hash[5], workspace[SHA_WORKSPACE_WORDS];
+       __u32 hash[5], workspace[SHA_WORKSPACE_WORDS];
+       __u8 extract[64];
 
        /* Generate a hash across the pool, 16 words (512 bits) at a time */
        sha_init(hash);
@@ -781,13 +782,13 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
         * brute-forcing the feedback as hard as brute-forcing the
         * hash.
         */
-       __add_entropy_words(r, hash, 5, extract);
+       mix_pool_bytes_extract(r, hash, sizeof(hash), extract);
 
        /*
         * To avoid duplicates, we atomically extract a portion of the
         * pool while mixing, and hash one final time.
         */
-       sha_transform(hash, (__u8 *)extract, workspace);
+       sha_transform(hash, extract, workspace);
        memset(extract, 0, sizeof(extract));
        memset(workspace, 0, sizeof(workspace));
 
@@ -894,9 +895,8 @@ static void init_std_data(struct entropy_store *r)
        spin_unlock_irqrestore(&r->lock, flags);
 
        now = ktime_get_real();
-       add_entropy_words(r, (__u32 *)&now, sizeof(now)/4);
-       add_entropy_words(r, (__u32 *)utsname(),
-                         sizeof(*(utsname()))/4);
+       mix_pool_bytes(r, &now, sizeof(now));
+       mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
 }
 
 static int rand_initialize(void)
@@ -1037,7 +1037,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
                count -= bytes;
                p += bytes;
 
-               add_entropy_words(r, buf, (bytes + 3) / 4);
+               mix_pool_bytes(r, buf, bytes);
                cond_resched();
        }
 
@@ -1079,7 +1079,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
                        return -EPERM;
                if (get_user(ent_count, p))
                        return -EFAULT;
-               credit_entropy_store(&input_pool, ent_count);
+               credit_entropy_bits(&input_pool, ent_count);
                return 0;
        case RNDADDENTROPY:
                if (!capable(CAP_SYS_ADMIN))
@@ -1094,7 +1094,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
                                    size);
                if (retval < 0)
                        return retval;
-               credit_entropy_store(&input_pool, ent_count);
+               credit_entropy_bits(&input_pool, ent_count);
                return 0;
        case RNDZAPENTCNT:
        case RNDCLEARPOOL:
@@ -1108,17 +1108,31 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
        }
 }
 
+static int random_fasync(int fd, struct file *filp, int on)
+{
+       return fasync_helper(fd, filp, on, &fasync);
+}
+
+static int random_release(struct inode *inode, struct file *filp)
+{
+       return fasync_helper(-1, filp, 0, &fasync);
+}
+
 const struct file_operations random_fops = {
        .read  = random_read,
        .write = random_write,
        .poll  = random_poll,
        .unlocked_ioctl = random_ioctl,
+       .fasync = random_fasync,
+       .release = random_release,
 };
 
 const struct file_operations urandom_fops = {
        .read  = urandom_read,
        .write = random_write,
        .unlocked_ioctl = random_ioctl,
+       .fasync = random_fasync,
+       .release = random_release,
 };
 
 /***************************************************************
@@ -1558,6 +1572,7 @@ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport)
 
        return half_md4_transform(hash, keyptr->secret);
 }
+EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral);
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,