Skip to content

Commit

Permalink
Merge tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/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
  • Loading branch information
torvalds committed Aug 6, 2014
2 parents bb2cbf5 + e02b876 commit f4f142e
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 131 deletions.
1 change: 1 addition & 0 deletions arch/x86/syscalls/syscall_32.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -361,3 +361,4 @@
352 i386 sched_getattr sys_sched_getattr
353 i386 renameat2 sys_renameat2
354 i386 seccomp sys_seccomp
355 i386 getrandom sys_getrandom
1 change: 1 addition & 0 deletions arch/x86/syscalls/syscall_64.tbl
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@
315 common sched_getattr sys_sched_getattr
316 common renameat2 sys_renameat2
317 common seccomp sys_seccomp
318 common getrandom sys_getrandom

#
# x32-specific system call numbers start at 512 to avoid cache impact
Expand Down
67 changes: 65 additions & 2 deletions drivers/char/hw_random/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -325,6 +347,36 @@ static int register_miscdev(void)
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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}

Expand Down
Loading

0 comments on commit f4f142e

Please sign in to comment.