random: group userspace read/write functions
[platform/kernel/linux-rpi.git] / drivers / char / random.c
index e9857a4..7d005f7 100644 (file)
@@ -1477,30 +1477,61 @@ static void try_to_generate_entropy(void)
        mix_pool_bytes(&stack.now, sizeof(stack.now));
 }
 
-static ssize_t urandom_read(struct file *file, char __user *buf, size_t nbytes,
-                           loff_t *ppos)
+
+/**********************************************************************
+ *
+ * Userspace reader/writer interfaces.
+ *
+ * getrandom(2) is the primary modern interface into the RNG and should
+ * be used in preference to anything else.
+ *
+ * Reading from /dev/random has the same functionality as calling
+ * getrandom(2) with flags=0. In earlier versions, however, it had
+ * vastly different semantics and should therefore be avoided, to
+ * prevent backwards compatibility issues.
+ *
+ * Reading from /dev/urandom has the same functionality as calling
+ * getrandom(2) with flags=GRND_INSECURE. Because it does not block
+ * waiting for the RNG to be ready, it should not be used.
+ *
+ * Writing to either /dev/random or /dev/urandom adds entropy to
+ * the input pool but does not credit it.
+ *
+ * Polling on /dev/random indicates when the RNG is initialized, on
+ * the read side, and when it wants new entropy, on the write side.
+ *
+ * Both /dev/random and /dev/urandom have the same set of ioctls for
+ * adding entropy, getting the entropy count, zeroing the count, and
+ * reseeding the crng.
+ *
+ **********************************************************************/
+
+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, unsigned int,
+               flags)
 {
-       static int maxwarn = 10;
+       if (flags & ~(GRND_NONBLOCK | GRND_RANDOM | GRND_INSECURE))
+               return -EINVAL;
 
-       if (!crng_ready() && maxwarn > 0) {
-               maxwarn--;
-               if (__ratelimit(&urandom_warning))
-                       pr_notice("%s: uninitialized urandom read (%zd bytes read)\n",
-                                 current->comm, nbytes);
-       }
+       /*
+        * Requesting insecure and blocking randomness at the same time makes
+        * no sense.
+        */
+       if ((flags & (GRND_INSECURE | GRND_RANDOM)) == (GRND_INSECURE | GRND_RANDOM))
+               return -EINVAL;
 
-       return get_random_bytes_user(buf, nbytes);
-}
+       if (count > INT_MAX)
+               count = INT_MAX;
 
-static ssize_t random_read(struct file *file, char __user *buf, size_t nbytes,
-                          loff_t *ppos)
-{
-       int ret;
+       if (!(flags & GRND_INSECURE) && !crng_ready()) {
+               int ret;
 
-       ret = wait_for_random_bytes();
-       if (ret != 0)
-               return ret;
-       return get_random_bytes_user(buf, nbytes);
+               if (flags & GRND_NONBLOCK)
+                       return -EAGAIN;
+               ret = wait_for_random_bytes();
+               if (unlikely(ret))
+                       return ret;
+       }
+       return get_random_bytes_user(buf, count);
 }
 
 static __poll_t random_poll(struct file *file, poll_table *wait)
@@ -1552,6 +1583,32 @@ static ssize_t random_write(struct file *file, const char __user *buffer,
        return (ssize_t)count;
 }
 
+static ssize_t urandom_read(struct file *file, char __user *buf, size_t nbytes,
+                           loff_t *ppos)
+{
+       static int maxwarn = 10;
+
+       if (!crng_ready() && maxwarn > 0) {
+               maxwarn--;
+               if (__ratelimit(&urandom_warning))
+                       pr_notice("%s: uninitialized urandom read (%zd bytes read)\n",
+                                 current->comm, nbytes);
+       }
+
+       return get_random_bytes_user(buf, nbytes);
+}
+
+static ssize_t random_read(struct file *file, char __user *buf, size_t nbytes,
+                          loff_t *ppos)
+{
+       int ret;
+
+       ret = wait_for_random_bytes();
+       if (ret != 0)
+               return ret;
+       return get_random_bytes_user(buf, nbytes);
+}
+
 static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 {
        int size, ent_count;
@@ -1560,7 +1617,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 
        switch (cmd) {
        case RNDGETENTCNT:
-               /* inherently racy, no point locking */
+               /* Inherently racy, no point locking. */
                if (put_user(input_pool.entropy_count, p))
                        return -EFAULT;
                return 0;
@@ -1636,34 +1693,6 @@ const struct file_operations urandom_fops = {
        .llseek = noop_llseek,
 };
 
-SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, unsigned int,
-               flags)
-{
-       if (flags & ~(GRND_NONBLOCK | GRND_RANDOM | GRND_INSECURE))
-               return -EINVAL;
-
-       /*
-        * Requesting insecure and blocking randomness at the same time makes
-        * no sense.
-        */
-       if ((flags & (GRND_INSECURE | GRND_RANDOM)) == (GRND_INSECURE | GRND_RANDOM))
-               return -EINVAL;
-
-       if (count > INT_MAX)
-               count = INT_MAX;
-
-       if (!(flags & GRND_INSECURE) && !crng_ready()) {
-               int ret;
-
-               if (flags & GRND_NONBLOCK)
-                       return -EAGAIN;
-               ret = wait_for_random_bytes();
-               if (unlikely(ret))
-                       return ret;
-       }
-       return get_random_bytes_user(buf, count);
-}
-
 /********************************************************************
  *
  * Sysctl interface