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
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
@@ -50,10 +51,22 @@
|
||||
|
||||
|
||||
static struct hwrng *current_rng;
|
||||
static struct task_struct *hwrng_fill;
|
||||
static LIST_HEAD(rng_list);
|
||||
static DEFINE_MUTEX(rng_mutex);
|
||||
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,
|
||||
int wait);
|
||||
@@ -89,6 +102,15 @@ static inline int hwrng_init(struct hwrng *rng)
|
||||
return ret;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -325,6 +347,36 @@ err_misc_dereg:
|
||||
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 err = -EINVAL;
|
||||
@@ -343,6 +395,13 @@ int hwrng_register(struct hwrng *rng)
|
||||
if (!rng_buffer)
|
||||
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. */
|
||||
err = -EEXIST;
|
||||
@@ -406,8 +465,11 @@ void hwrng_unregister(struct hwrng *rng)
|
||||
current_rng = NULL;
|
||||
}
|
||||
}
|
||||
if (list_empty(&rng_list))
|
||||
if (list_empty(&rng_list)) {
|
||||
unregister_miscdev();
|
||||
if (hwrng_fill)
|
||||
kthread_stop(hwrng_fill);
|
||||
}
|
||||
|
||||
mutex_unlock(&rng_mutex);
|
||||
}
|
||||
@@ -418,6 +480,7 @@ static void __exit hwrng_exit(void)
|
||||
mutex_lock(&rng_mutex);
|
||||
BUG_ON(current_rng);
|
||||
kfree(rng_buffer);
|
||||
kfree(rng_fillbuf);
|
||||
mutex_unlock(&rng_mutex);
|
||||
}
|
||||
|
||||
|
مرجع در شماره جدید
Block a user