You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+186
-127
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,8 @@
|
||||
* @read: New API. drivers can fill up to max bytes of data
|
||||
* into the buffer. The buffer is aligned for any type.
|
||||
* @priv: Private data, for use by the RNG driver.
|
||||
* @quality: Estimation of true entropy in RNG's bitstream
|
||||
* (per mill).
|
||||
*/
|
||||
struct hwrng {
|
||||
const char *name;
|
||||
@@ -38,6 +40,7 @@ struct hwrng {
|
||||
int (*data_read)(struct hwrng *rng, u32 *data);
|
||||
int (*read)(struct hwrng *rng, void *data, size_t max, bool wait);
|
||||
unsigned long priv;
|
||||
unsigned short quality;
|
||||
|
||||
/* internal. */
|
||||
struct list_head list;
|
||||
@@ -47,5 +50,7 @@ struct hwrng {
|
||||
extern int hwrng_register(struct hwrng *rng);
|
||||
/** Unregister a Hardware Random Number Generator driver. */
|
||||
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_ */
|
||||
|
||||
@@ -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_seccomp(unsigned int op, unsigned int flags,
|
||||
const char __user *uargs);
|
||||
asmlinkage long sys_getrandom(char __user *buf, size_t count,
|
||||
unsigned int flags);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -701,9 +701,11 @@ __SYSCALL(__NR_sched_getattr, sys_sched_getattr)
|
||||
__SYSCALL(__NR_renameat2, sys_renameat2)
|
||||
#define __NR_seccomp 277
|
||||
__SYSCALL(__NR_seccomp, sys_seccomp)
|
||||
#define __NR_getrandom 278
|
||||
__SYSCALL(__NR_getrandom, sys_getrandom)
|
||||
|
||||
#undef __NR_syscalls
|
||||
#define __NR_syscalls 278
|
||||
#define __NR_syscalls 279
|
||||
|
||||
/*
|
||||
* All syscalls below here should go away really,
|
||||
|
||||
@@ -40,4 +40,13 @@ struct rand_pool_info {
|
||||
__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 */
|
||||
|
||||
Reference in New Issue
Block a user