Commit f4f142ed authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random

Pull randomness updates from Ted Ts'o:
 "Cleanups and bug fixes to /dev/random, add a new getrandom(2) system
  call, which is a superset of OpenBSD's getentropy(2) call, for use
  with userspace crypto libraries such as LibreSSL.

  Also add the ability to have a kernel thread to pull entropy from
  hardware rng devices into /dev/random"

* tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/random:
  hwrng: Pass entropy to add_hwgenerator_randomness() in bits, not bytes
  random: limit the contribution of the hw rng to at most half
  random: introduce getrandom(2) system call
  hw_random: fix sparse warning (NULL vs 0 for pointer)
  random: use registers from interrupted code for CPU's w/o a cycle counter
  hwrng: add per-device entropy derating
  hwrng: create filler thread
  random: add_hwgenerator_randomness() for feeding entropy from devices
  random: use an improved fast_mix() function
  random: clean up interrupt entropy accounting for archs w/o cycle counters
  random: only update the last_pulled time if we actually transferred entropy
  random: remove unneeded hash of a portion of the entropy pool
  random: always update the entropy pool under the spinlock
parents bb2cbf5e e02b8765
...@@ -361,3 +361,4 @@ ...@@ -361,3 +361,4 @@
352 i386 sched_getattr sys_sched_getattr 352 i386 sched_getattr sys_sched_getattr
353 i386 renameat2 sys_renameat2 353 i386 renameat2 sys_renameat2
354 i386 seccomp sys_seccomp 354 i386 seccomp sys_seccomp
355 i386 getrandom sys_getrandom
...@@ -324,6 +324,7 @@ ...@@ -324,6 +324,7 @@
315 common sched_getattr sys_sched_getattr 315 common sched_getattr sys_sched_getattr
316 common renameat2 sys_renameat2 316 common renameat2 sys_renameat2
317 common seccomp sys_seccomp 317 common seccomp sys_seccomp
318 common getrandom sys_getrandom
# #
# x32-specific system call numbers start at 512 to avoid cache impact # x32-specific system call numbers start at 512 to avoid cache impact
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/kthread.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/random.h> #include <linux/random.h>
...@@ -50,10 +51,22 @@ ...@@ -50,10 +51,22 @@
static struct hwrng *current_rng; static struct hwrng *current_rng;
static struct task_struct *hwrng_fill;
static LIST_HEAD(rng_list); static LIST_HEAD(rng_list);
static DEFINE_MUTEX(rng_mutex); static DEFINE_MUTEX(rng_mutex);
static int data_avail; static int data_avail;
static u8 *rng_buffer; static u8 *rng_buffer, *rng_fillbuf;
static unsigned short current_quality;
static unsigned short default_quality; /* = 0; default to "off" */
module_param(current_quality, ushort, 0644);
MODULE_PARM_DESC(current_quality,
"current hwrng entropy estimation per mill");
module_param(default_quality, ushort, 0644);
MODULE_PARM_DESC(default_quality,
"default entropy content of hwrng per mill");
static void start_khwrngd(void);
static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size, static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
int wait); int wait);
...@@ -89,6 +102,15 @@ static inline int hwrng_init(struct hwrng *rng) ...@@ -89,6 +102,15 @@ static inline int hwrng_init(struct hwrng *rng)
return ret; return ret;
} }
add_early_randomness(rng); add_early_randomness(rng);
current_quality = rng->quality ? : default_quality;
current_quality &= 1023;
if (current_quality == 0 && hwrng_fill)
kthread_stop(hwrng_fill);
if (current_quality > 0 && !hwrng_fill)
start_khwrngd();
return 0; return 0;
} }
...@@ -325,6 +347,36 @@ static int register_miscdev(void) ...@@ -325,6 +347,36 @@ static int register_miscdev(void)
goto out; goto out;
} }
static int hwrng_fillfn(void *unused)
{
long rc;
while (!kthread_should_stop()) {
if (!current_rng)
break;
rc = rng_get_data(current_rng, rng_fillbuf,
rng_buffer_size(), 1);
if (rc <= 0) {
pr_warn("hwrng: no data available\n");
msleep_interruptible(10000);
continue;
}
add_hwgenerator_randomness((void *)rng_fillbuf, rc,
rc * current_quality * 8 >> 10);
}
hwrng_fill = NULL;
return 0;
}
static void start_khwrngd(void)
{
hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng");
if (hwrng_fill == ERR_PTR(-ENOMEM)) {
pr_err("hwrng_fill thread creation failed");
hwrng_fill = NULL;
}
}
int hwrng_register(struct hwrng *rng) int hwrng_register(struct hwrng *rng)
{ {
int err = -EINVAL; int err = -EINVAL;
...@@ -343,6 +395,13 @@ int hwrng_register(struct hwrng *rng) ...@@ -343,6 +395,13 @@ int hwrng_register(struct hwrng *rng)
if (!rng_buffer) if (!rng_buffer)
goto out_unlock; goto out_unlock;
} }
if (!rng_fillbuf) {
rng_fillbuf = kmalloc(rng_buffer_size(), GFP_KERNEL);
if (!rng_fillbuf) {
kfree(rng_buffer);
goto out_unlock;
}
}
/* Must not register two RNGs with the same name. */ /* Must not register two RNGs with the same name. */
err = -EEXIST; err = -EEXIST;
...@@ -406,8 +465,11 @@ void hwrng_unregister(struct hwrng *rng) ...@@ -406,8 +465,11 @@ void hwrng_unregister(struct hwrng *rng)
current_rng = NULL; current_rng = NULL;
} }
} }
if (list_empty(&rng_list)) if (list_empty(&rng_list)) {
unregister_miscdev(); unregister_miscdev();
if (hwrng_fill)
kthread_stop(hwrng_fill);
}
mutex_unlock(&rng_mutex); mutex_unlock(&rng_mutex);
} }
...@@ -418,6 +480,7 @@ static void __exit hwrng_exit(void) ...@@ -418,6 +480,7 @@ static void __exit hwrng_exit(void)
mutex_lock(&rng_mutex); mutex_lock(&rng_mutex);
BUG_ON(current_rng); BUG_ON(current_rng);
kfree(rng_buffer); kfree(rng_buffer);
kfree(rng_fillbuf);
mutex_unlock(&rng_mutex); mutex_unlock(&rng_mutex);
} }
......
This diff is collapsed.
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
* @read: New API. drivers can fill up to max bytes of data * @read: New API. drivers can fill up to max bytes of data
* into the buffer. The buffer is aligned for any type. * into the buffer. The buffer is aligned for any type.
* @priv: Private data, for use by the RNG driver. * @priv: Private data, for use by the RNG driver.
* @quality: Estimation of true entropy in RNG's bitstream
* (per mill).
*/ */
struct hwrng { struct hwrng {
const char *name; const char *name;
...@@ -38,6 +40,7 @@ struct hwrng { ...@@ -38,6 +40,7 @@ struct hwrng {
int (*data_read)(struct hwrng *rng, u32 *data); int (*data_read)(struct hwrng *rng, u32 *data);
int (*read)(struct hwrng *rng, void *data, size_t max, bool wait); int (*read)(struct hwrng *rng, void *data, size_t max, bool wait);
unsigned long priv; unsigned long priv;
unsigned short quality;
/* internal. */ /* internal. */
struct list_head list; struct list_head list;
...@@ -47,5 +50,7 @@ struct hwrng { ...@@ -47,5 +50,7 @@ struct hwrng {
extern int hwrng_register(struct hwrng *rng); extern int hwrng_register(struct hwrng *rng);
/** Unregister a Hardware Random Number Generator driver. */ /** Unregister a Hardware Random Number Generator driver. */
extern void hwrng_unregister(struct hwrng *rng); extern void hwrng_unregister(struct hwrng *rng);
/** Feed random bits into the pool. */
extern void add_hwgenerator_randomness(const char *buffer, size_t count, size_t entropy);
#endif /* LINUX_HWRANDOM_H_ */ #endif /* LINUX_HWRANDOM_H_ */
...@@ -868,4 +868,7 @@ asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, ...@@ -868,4 +868,7 @@ asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type,
asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags); asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags);
asmlinkage long sys_seccomp(unsigned int op, unsigned int flags, asmlinkage long sys_seccomp(unsigned int op, unsigned int flags,
const char __user *uargs); const char __user *uargs);
asmlinkage long sys_getrandom(char __user *buf, size_t count,
unsigned int flags);
#endif #endif
...@@ -701,9 +701,11 @@ __SYSCALL(__NR_sched_getattr, sys_sched_getattr) ...@@ -701,9 +701,11 @@ __SYSCALL(__NR_sched_getattr, sys_sched_getattr)
__SYSCALL(__NR_renameat2, sys_renameat2) __SYSCALL(__NR_renameat2, sys_renameat2)
#define __NR_seccomp 277 #define __NR_seccomp 277
__SYSCALL(__NR_seccomp, sys_seccomp) __SYSCALL(__NR_seccomp, sys_seccomp)
#define __NR_getrandom 278
__SYSCALL(__NR_getrandom, sys_getrandom)
#undef __NR_syscalls #undef __NR_syscalls
#define __NR_syscalls 278 #define __NR_syscalls 279
/* /*
* All syscalls below here should go away really, * All syscalls below here should go away really,
......
...@@ -40,4 +40,13 @@ struct rand_pool_info { ...@@ -40,4 +40,13 @@ struct rand_pool_info {
__u32 buf[0]; __u32 buf[0];
}; };
/*
* Flags for getrandom(2)
*
* GRND_NONBLOCK Don't block and return EAGAIN instead
* GRND_RANDOM Use the /dev/random pool instead of /dev/urandom
*/
#define GRND_NONBLOCK 0x0001
#define GRND_RANDOM 0x0002
#endif /* _UAPI_LINUX_RANDOM_H */ #endif /* _UAPI_LINUX_RANDOM_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment