random(4): Simplify RANDOM_LOADABLE
Simplify RANDOM_LOADABLE by removing the ability to unload a LOADABLE random(4) implementation. This allows one-time random module selection at boot, by loader(8). Swapping modules on the fly doesn't seem especially useful. This removes the need to hold a lock over the sleepable module calls read_random and read_random_uio. init/deinit have been pulled out of random_algorithm entirely. Algorithms can run their own sysinits to initialize; deinit is removed entirely, as algorithms can not be unloaded. Algorithms should initialize at SI_SUB_RANDOM:SI_ORDER_SECOND. In LOADABLE systems, algorithms install a pointer to their local random_algorithm context in p_random_alg_context at that time. Go ahead and const'ify random_algorithm objects; there is no need to mutate them at runtime. LOADABLE kernel NULL checks are removed from random_harvestq by ordering random_harvestq initialization at SI_SUB_RANDOM:SI_ORDER_THIRD, after algorithm init. Prior to random_harvestq init, hc_harvest_mask is zero and no events are forwarded to algorithms; after random_harvestq init, the relevant pointers will already have been installed. Remove the bulk of random_infra shim wrappers and instead expose the bare function pointers in sys/random.h. In LOADABLE systems, read_random(9) et al are just thin shim macros around invoking the associated function pointer. We do not provide a registration system but instead expect LOADABLE modules to register themselves at SI_SUB_RANDOM:SI_ORDER_SECOND. An example is provided in randomdev.c, as used in the random_fortuna.ko module. Approved by: csprng(markm) Discussed with: gordon Differential Revision: https://reviews.freebsd.org/D22512
This commit is contained in:
parent
af00898b5d
commit
3ee1d5bb9d
3
UPDATING
3
UPDATING
@ -26,6 +26,9 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW:
|
||||
disable the most expensive debugging functionality run
|
||||
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
||||
|
||||
20191226:
|
||||
Kernel-loadable random(4) modules are no longer unloadable.
|
||||
|
||||
20191222:
|
||||
Clang, llvm, lld, lldb, compiler-rt, libc++, libunwind and openmp have
|
||||
been upgraded to 9.0.1. Please see the 20141231 entry below for
|
||||
|
@ -261,15 +261,14 @@ static void random_fortuna_read(uint8_t *, size_t);
|
||||
static bool random_fortuna_seeded(void);
|
||||
static bool random_fortuna_seeded_internal(void);
|
||||
static void random_fortuna_process_event(struct harvest_event *);
|
||||
static void random_fortuna_init_alg(void *);
|
||||
static void random_fortuna_deinit_alg(void *);
|
||||
|
||||
static void random_fortuna_reseed_internal(uint32_t *entropy_data, u_int blockcount);
|
||||
|
||||
struct random_algorithm random_alg_context = {
|
||||
#ifdef RANDOM_LOADABLE
|
||||
static
|
||||
#endif
|
||||
const struct random_algorithm random_alg_context = {
|
||||
.ra_ident = "Fortuna",
|
||||
.ra_init_alg = random_fortuna_init_alg,
|
||||
.ra_deinit_alg = random_fortuna_deinit_alg,
|
||||
.ra_pre_read = random_fortuna_pre_read,
|
||||
.ra_read = random_fortuna_read,
|
||||
.ra_seeded = random_fortuna_seeded,
|
||||
@ -286,6 +285,10 @@ random_fortuna_init_alg(void *unused __unused)
|
||||
struct sysctl_oid *random_fortuna_o;
|
||||
#endif
|
||||
|
||||
#ifdef RANDOM_LOADABLE
|
||||
p_random_alg_context = &random_alg_context;
|
||||
#endif
|
||||
|
||||
RANDOM_RESEED_INIT_LOCK();
|
||||
/*
|
||||
* Fortuna parameters. Do not adjust these unless you have
|
||||
@ -330,18 +333,8 @@ random_fortuna_init_alg(void *unused __unused)
|
||||
fortuna_state.fs_counter = UINT128_ZERO;
|
||||
explicit_bzero(&fortuna_state.fs_key, sizeof(fortuna_state.fs_key));
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
random_fortuna_deinit_alg(void *unused __unused)
|
||||
{
|
||||
|
||||
RANDOM_RESEED_DEINIT_LOCK();
|
||||
explicit_bzero(&fortuna_state, sizeof(fortuna_state));
|
||||
#ifdef _KERNEL
|
||||
sysctl_ctx_free(&random_clist);
|
||||
#endif
|
||||
}
|
||||
SYSINIT(random_alg, SI_SUB_RANDOM, SI_ORDER_SECOND, random_fortuna_init_alg,
|
||||
NULL);
|
||||
|
||||
/*-
|
||||
* FS&K - AddRandomEvent()
|
||||
|
@ -87,8 +87,6 @@ static void random_other_pre_read(void);
|
||||
static void random_other_read(uint8_t *, size_t);
|
||||
static bool random_other_seeded(void);
|
||||
static void random_other_process_event(struct harvest_event *);
|
||||
static void random_other_init_alg(void *);
|
||||
static void random_other_deinit_alg(void *);
|
||||
|
||||
/*
|
||||
* RANDOM_OTHER_NPOOLS is used when reading hardware random
|
||||
@ -97,10 +95,11 @@ static void random_other_deinit_alg(void *);
|
||||
*/
|
||||
#define RANDOM_OTHER_NPOOLS 1
|
||||
|
||||
struct random_algorithm random_alg_context = {
|
||||
#ifdef RANDOM_LOADABLE
|
||||
static
|
||||
#endif
|
||||
const struct random_algorithm random_alg_context = {
|
||||
.ra_ident = "other",
|
||||
.ra_init_alg = random_other_init_alg,
|
||||
.ra_deinit_alg = random_other_deinit_alg,
|
||||
.ra_pre_read = random_other_pre_read,
|
||||
.ra_read = random_other_read,
|
||||
.ra_seeded = random_other_seeded,
|
||||
@ -112,34 +111,20 @@ struct random_algorithm random_alg_context = {
|
||||
static mtx_t other_mtx;
|
||||
|
||||
/*
|
||||
* void random_other_init_alg(void *unused __unused)
|
||||
*
|
||||
* Do algorithm-specific initialisation here.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
random_other_init_alg(void *unused __unused)
|
||||
{
|
||||
|
||||
#ifdef RANDOM_LOADABLE
|
||||
p_random_alg_context = &random_alg_context;
|
||||
#endif
|
||||
|
||||
RANDOM_RESEED_INIT_LOCK();
|
||||
/*
|
||||
* Do set-up work here!
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* void random_other_deinit_alg(void *unused __unused)
|
||||
*
|
||||
* Do algorithm-specific deinitialisation here.
|
||||
*/
|
||||
static void
|
||||
random_other_deinit_alg(void *unused __unused)
|
||||
{
|
||||
|
||||
/*
|
||||
* Do tear-down work here!
|
||||
*/
|
||||
RANDOM_RESEED_DEINIT_LOCK();
|
||||
}
|
||||
SYSINIT(random_alg, SI_SUB_RANDOM, SI_ORDER_SECOND, random_other_init_alg,
|
||||
NULL);
|
||||
|
||||
/*
|
||||
* void random_other_pre_read(void)
|
||||
|
@ -49,11 +49,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/unistd.h>
|
||||
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
#include <sys/lock.h>
|
||||
#include <sys/sx.h>
|
||||
#endif
|
||||
|
||||
#include <machine/atomic.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
@ -163,14 +158,7 @@ static struct kproc_desc random_proc_kp = {
|
||||
static __inline void
|
||||
random_harvestq_fast_process_event(struct harvest_event *event)
|
||||
{
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
RANDOM_CONFIG_S_LOCK();
|
||||
if (p_random_alg_context)
|
||||
#endif
|
||||
p_random_alg_context->ra_event_processor(event);
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
RANDOM_CONFIG_S_UNLOCK();
|
||||
#endif
|
||||
explicit_bzero(event, sizeof(*event));
|
||||
}
|
||||
|
||||
@ -230,11 +218,6 @@ random_sources_feed(void)
|
||||
* Step over all of live entropy sources, and feed their output
|
||||
* to the system-wide RNG.
|
||||
*/
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
RANDOM_CONFIG_S_LOCK();
|
||||
if (p_random_alg_context) {
|
||||
/* It's an indenting error. Yeah, Yeah. */
|
||||
#endif
|
||||
local_read_rate = atomic_readandclear_32(&read_rate);
|
||||
/* Perform at least one read per round */
|
||||
local_read_rate = MAX(local_read_rate, 1);
|
||||
@ -261,10 +244,6 @@ random_sources_feed(void)
|
||||
}
|
||||
}
|
||||
explicit_bzero(entropy, sizeof(entropy));
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
}
|
||||
RANDOM_CONFIG_S_UNLOCK();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -396,7 +375,7 @@ random_harvestq_init(void *unused __unused)
|
||||
RANDOM_HARVEST_INIT_LOCK();
|
||||
harvest_context.hc_entropy_ring.in = harvest_context.hc_entropy_ring.out = 0;
|
||||
}
|
||||
SYSINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_SECOND, random_harvestq_init, NULL);
|
||||
SYSINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_THIRD, random_harvestq_init, NULL);
|
||||
|
||||
/*
|
||||
* Subroutine to slice up a contiguous chunk of 'entropy' and feed it into the
|
||||
@ -485,7 +464,7 @@ random_harvestq_deinit(void *unused __unused)
|
||||
while (random_kthread_control >= 0)
|
||||
tsleep(&harvest_context.hc_kthread_proc, 0, "harvqterm", hz/5);
|
||||
}
|
||||
SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_SECOND, random_harvestq_deinit, NULL);
|
||||
SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_THIRD, random_harvestq_deinit, NULL);
|
||||
|
||||
/*-
|
||||
* Entropy harvesting queue routine.
|
||||
|
@ -35,11 +35,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/random.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
#include <sys/lock.h>
|
||||
#include <sys/sx.h>
|
||||
#endif
|
||||
|
||||
#include <dev/random/randomdev.h>
|
||||
|
||||
/* Set up the sysctl root node for the entropy device */
|
||||
@ -102,107 +97,8 @@ SYSCTL_BOOL(_kern_random_initial_seeding, OID_AUTO,
|
||||
MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures");
|
||||
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
struct random_algorithm *p_random_alg_context = NULL;
|
||||
#else /* !defined(RANDOM_LOADABLE) */
|
||||
struct random_algorithm *p_random_alg_context = &random_alg_context;
|
||||
#endif /* defined(RANDOM_LOADABLE) */
|
||||
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
|
||||
static void
|
||||
null_read_random(void *dummy __unused, u_int dummy2 __unused)
|
||||
{
|
||||
panic("%s: no random module is loaded", __func__);
|
||||
}
|
||||
|
||||
static bool
|
||||
null_is_random_seeded(void)
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
struct random_readers {
|
||||
int (*read_random_uio)(struct uio *, bool);
|
||||
void (*read_random)(void *, u_int);
|
||||
bool (*is_random_seeded)(void);
|
||||
} random_reader_context = {
|
||||
(int (*)(struct uio *, bool))nullop,
|
||||
null_read_random,
|
||||
null_is_random_seeded,
|
||||
};
|
||||
|
||||
struct sx randomdev_config_lock;
|
||||
|
||||
static void
|
||||
random_infra_sysinit(void *dummy __unused)
|
||||
{
|
||||
|
||||
RANDOM_CONFIG_INIT_LOCK();
|
||||
}
|
||||
SYSINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_FIRST, random_infra_sysinit, NULL);
|
||||
|
||||
void
|
||||
random_infra_init(int (*p_random_read_uio)(struct uio *, bool),
|
||||
void (*p_random_read)(void *, u_int),
|
||||
bool (*p_is_random_seeded)(void))
|
||||
{
|
||||
|
||||
RANDOM_CONFIG_X_LOCK();
|
||||
random_reader_context.read_random_uio = p_random_read_uio;
|
||||
random_reader_context.read_random = p_random_read;
|
||||
random_reader_context.is_random_seeded = p_is_random_seeded;
|
||||
RANDOM_CONFIG_X_UNLOCK();
|
||||
}
|
||||
|
||||
void
|
||||
random_infra_uninit(void)
|
||||
{
|
||||
|
||||
RANDOM_CONFIG_X_LOCK();
|
||||
random_reader_context.read_random_uio = (int (*)(struct uio *, bool))nullop;
|
||||
random_reader_context.read_random = null_read_random;
|
||||
random_reader_context.is_random_seeded = null_is_random_seeded;
|
||||
RANDOM_CONFIG_X_UNLOCK();
|
||||
}
|
||||
|
||||
static void
|
||||
random_infra_sysuninit(void *dummy __unused)
|
||||
{
|
||||
|
||||
RANDOM_CONFIG_DEINIT_LOCK();
|
||||
}
|
||||
SYSUNINIT(random_device_h_init, SI_SUB_RANDOM, SI_ORDER_FIRST, random_infra_sysuninit, NULL);
|
||||
|
||||
int
|
||||
read_random_uio(struct uio *uio, bool nonblock)
|
||||
{
|
||||
int retval;
|
||||
|
||||
RANDOM_CONFIG_S_LOCK();
|
||||
retval = random_reader_context.read_random_uio(uio, nonblock);
|
||||
RANDOM_CONFIG_S_UNLOCK();
|
||||
return (retval);
|
||||
}
|
||||
|
||||
void
|
||||
read_random(void *buf, u_int len)
|
||||
{
|
||||
|
||||
RANDOM_CONFIG_S_LOCK();
|
||||
random_reader_context.read_random(buf, len);
|
||||
RANDOM_CONFIG_S_UNLOCK();
|
||||
}
|
||||
|
||||
bool
|
||||
is_random_seeded(void)
|
||||
{
|
||||
bool result;
|
||||
|
||||
RANDOM_CONFIG_S_LOCK();
|
||||
result = random_reader_context.is_random_seeded();
|
||||
RANDOM_CONFIG_S_UNLOCK();
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
const struct random_algorithm *p_random_alg_context;
|
||||
void (*_read_random)(void *, u_int);
|
||||
int (*_read_random_uio)(struct uio *, bool);
|
||||
bool (*_is_random_seeded)(void);
|
||||
#endif /* defined(RANDOM_LOADABLE) */
|
||||
|
@ -59,17 +59,17 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#define RANDOM_UNIT 0
|
||||
|
||||
/*
|
||||
* In loadable random, the core randomdev.c / random(9) routines have static
|
||||
* visibility and an alternative name to avoid conflicting with the function
|
||||
* pointers of the real names in the core kernel. random_alg_context_init
|
||||
* installs pointers to the loadable static names into the core kernel's
|
||||
* function pointers at SI_SUB_RANDOM:SI_ORDER_SECOND.
|
||||
*/
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
#define READ_RANDOM_UIO _read_random_uio
|
||||
#define READ_RANDOM _read_random
|
||||
#define IS_RANDOM_SEEDED _is_random_seeded
|
||||
static int READ_RANDOM_UIO(struct uio *, bool);
|
||||
static void READ_RANDOM(void *, u_int);
|
||||
static bool IS_RANDOM_SEEDED(void);
|
||||
#else
|
||||
#define READ_RANDOM_UIO read_random_uio
|
||||
#define READ_RANDOM read_random
|
||||
#define IS_RANDOM_SEEDED is_random_seeded
|
||||
static int (read_random_uio)(struct uio *, bool);
|
||||
static void (read_random)(void *, u_int);
|
||||
static bool (is_random_seeded)(void);
|
||||
#endif
|
||||
|
||||
static d_read_t randomdev_read;
|
||||
@ -89,30 +89,17 @@ static struct cdevsw random_cdevsw = {
|
||||
/* For use with make_dev(9)/destroy_dev(9). */
|
||||
static struct cdev *random_dev;
|
||||
|
||||
static void
|
||||
random_alg_context_ra_init_alg(void *data)
|
||||
{
|
||||
|
||||
p_random_alg_context = &random_alg_context;
|
||||
p_random_alg_context->ra_init_alg(data);
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
random_infra_init(READ_RANDOM_UIO, READ_RANDOM, IS_RANDOM_SEEDED);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
random_alg_context_ra_deinit_alg(void *data)
|
||||
random_alg_context_init(void *dummy __unused)
|
||||
{
|
||||
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
random_infra_uninit();
|
||||
#endif
|
||||
p_random_alg_context->ra_deinit_alg(data);
|
||||
p_random_alg_context = NULL;
|
||||
_read_random_uio = (read_random_uio);
|
||||
_read_random = (read_random);
|
||||
_is_random_seeded = (is_random_seeded);
|
||||
}
|
||||
|
||||
SYSINIT(random_device, SI_SUB_RANDOM, SI_ORDER_THIRD, random_alg_context_ra_init_alg, NULL);
|
||||
SYSUNINIT(random_device, SI_SUB_RANDOM, SI_ORDER_THIRD, random_alg_context_ra_deinit_alg, NULL);
|
||||
SYSINIT(random_device, SI_SUB_RANDOM, SI_ORDER_SECOND, random_alg_context_init,
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
static struct selinfo rsel;
|
||||
|
||||
@ -124,7 +111,7 @@ static int
|
||||
randomdev_read(struct cdev *dev __unused, struct uio *uio, int flags)
|
||||
{
|
||||
|
||||
return (READ_RANDOM_UIO(uio, (flags & O_NONBLOCK) != 0));
|
||||
return ((read_random_uio)(uio, (flags & O_NONBLOCK) != 0));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -154,7 +141,7 @@ randomdev_wait_until_seeded(bool interruptible)
|
||||
if (spamcount == 0)
|
||||
printf("random: %s unblock wait\n", __func__);
|
||||
spamcount = (spamcount + 1) % 100;
|
||||
error = tsleep(&random_alg_context, slpflags, "randseed",
|
||||
error = tsleep(p_random_alg_context, slpflags, "randseed",
|
||||
hz / 10);
|
||||
if (error == ERESTART || error == EINTR) {
|
||||
KASSERT(interruptible,
|
||||
@ -170,7 +157,7 @@ randomdev_wait_until_seeded(bool interruptible)
|
||||
}
|
||||
|
||||
int
|
||||
READ_RANDOM_UIO(struct uio *uio, bool nonblock)
|
||||
(read_random_uio)(struct uio *uio, bool nonblock)
|
||||
{
|
||||
/* 16 MiB takes about 0.08 s CPU time on my 2017 AMD Zen CPU */
|
||||
#define SIGCHK_PERIOD (16 * 1024 * 1024)
|
||||
@ -238,7 +225,7 @@ READ_RANDOM_UIO(struct uio *uio, bool nonblock)
|
||||
*/
|
||||
if (error == 0 && uio->uio_resid != 0 &&
|
||||
total_read % sigchk_period == 0) {
|
||||
error = tsleep_sbt(&random_alg_context, PCATCH,
|
||||
error = tsleep_sbt(p_random_alg_context, PCATCH,
|
||||
"randrd", SBT_1NS, 0, C_HARDCLOCK);
|
||||
/* Squash tsleep timeout condition */
|
||||
if (error == EWOULDBLOCK)
|
||||
@ -271,7 +258,7 @@ READ_RANDOM_UIO(struct uio *uio, bool nonblock)
|
||||
* 'kern.random.initial_seeding.read_random_bypassed_before_seeding'.
|
||||
*/
|
||||
void
|
||||
READ_RANDOM(void *random_buf, u_int len)
|
||||
(read_random)(void *random_buf, u_int len)
|
||||
{
|
||||
|
||||
KASSERT(random_buf != NULL, ("No suitable random buffer in %s", __func__));
|
||||
@ -305,7 +292,7 @@ READ_RANDOM(void *random_buf, u_int len)
|
||||
}
|
||||
|
||||
bool
|
||||
IS_RANDOM_SEEDED(void)
|
||||
(is_random_seeded)(void)
|
||||
{
|
||||
return (p_random_alg_context->ra_seeded());
|
||||
}
|
||||
@ -356,7 +343,7 @@ randomdev_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
|
||||
if (error)
|
||||
break;
|
||||
randomdev_accumulate(random_buf, c);
|
||||
tsleep(&random_alg_context, 0, "randwr", hz/10);
|
||||
tsleep(p_random_alg_context, 0, "randwr", hz/10);
|
||||
}
|
||||
if (nbytes != uio->uio_resid && (error == ERESTART || error == EINTR))
|
||||
/* Partial write, not error. */
|
||||
@ -385,7 +372,7 @@ randomdev_unblock(void)
|
||||
{
|
||||
|
||||
selwakeuppri(&rsel, PUSER);
|
||||
wakeup(&random_alg_context);
|
||||
wakeup(p_random_alg_context);
|
||||
printf("random: unblocking device.\n");
|
||||
/* Do random(9) a favour while we are about it. */
|
||||
(void)atomic_cmpset_int(&arc4rand_iniseed_state, ARC4_ENTR_NONE, ARC4_ENTR_HAVE);
|
||||
@ -424,7 +411,7 @@ randomdev_modevent(module_t mod __unused, int type, void *data __unused)
|
||||
make_dev_alias(random_dev, "urandom"); /* compatibility */
|
||||
break;
|
||||
case MOD_UNLOAD:
|
||||
destroy_dev(random_dev);
|
||||
error = EBUSY;
|
||||
break;
|
||||
case MOD_SHUTDOWN:
|
||||
break;
|
||||
|
@ -79,15 +79,18 @@ typedef u_int random_source_read_t(void *, u_int);
|
||||
struct random_algorithm {
|
||||
const char *ra_ident;
|
||||
u_int ra_poolcount;
|
||||
void (*ra_init_alg)(void *);
|
||||
void (*ra_deinit_alg)(void *);
|
||||
random_alg_pre_read_t *ra_pre_read;
|
||||
random_alg_read_t *ra_read;
|
||||
random_alg_seeded_t *ra_seeded;
|
||||
random_alg_eventprocessor_t *ra_event_processor;
|
||||
};
|
||||
|
||||
extern struct random_algorithm random_alg_context, *p_random_alg_context;
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
extern const struct random_algorithm *p_random_alg_context;
|
||||
#else
|
||||
extern const struct random_algorithm random_alg_context;
|
||||
#define p_random_alg_context (&random_alg_context)
|
||||
#endif
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
@ -105,19 +108,6 @@ struct random_source {
|
||||
void random_source_register(struct random_source *);
|
||||
void random_source_deregister(struct random_source *);
|
||||
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
extern struct sx randomdev_config_lock;
|
||||
#define RANDOM_CONFIG_INIT_LOCK(x) sx_init(&randomdev_config_lock, "configuration change lock")
|
||||
#define RANDOM_CONFIG_X_LOCK(x) sx_xlock(&randomdev_config_lock)
|
||||
#define RANDOM_CONFIG_X_UNLOCK(x) sx_xunlock(&randomdev_config_lock)
|
||||
#define RANDOM_CONFIG_S_LOCK(x) sx_slock(&randomdev_config_lock)
|
||||
#define RANDOM_CONFIG_S_UNLOCK(x) sx_sunlock(&randomdev_config_lock)
|
||||
#define RANDOM_CONFIG_DEINIT_LOCK(x) sx_destroy(&randomdev_config_lock)
|
||||
void random_infra_init(int (*)(struct uio *, bool), void (*)(void *, u_int),
|
||||
bool (*)(void));
|
||||
void random_infra_uninit(void);
|
||||
#endif
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
void randomdev_unblock(void);
|
||||
|
@ -37,9 +37,35 @@
|
||||
|
||||
struct uio;
|
||||
|
||||
/*
|
||||
* In the loadable random world, there are set of dangling pointers left in the
|
||||
* core kernel:
|
||||
* * read_random, read_random_uio, is_random_seeded are function pointers,
|
||||
* rather than functions.
|
||||
* * p_random_alg_context is a true pointer in loadable random kernels.
|
||||
*
|
||||
* These are initialized at SI_SUB_RANDOM:SI_ORDER_SECOND during boot. The
|
||||
* read-type pointers are initialized by random_alg_context_init() in
|
||||
* randomdev.c and p_random_alg_context in the algorithm, e.g., fortuna.c's
|
||||
* random_fortuna_init_alg(). The nice thing about function pointers is they
|
||||
* have a similar calling convention to ordinary functions.
|
||||
*
|
||||
* (In !loadable, the read_random, etc, routines are just plain functions;
|
||||
* p_random_alg_context is a macro for the public visibility
|
||||
* &random_alg_context.)
|
||||
*/
|
||||
#if defined(RANDOM_LOADABLE)
|
||||
extern void (*_read_random)(void *, u_int);
|
||||
extern int (*_read_random_uio)(struct uio *, bool);
|
||||
extern bool (*_is_random_seeded)(void);
|
||||
#define read_random(a, b) (*_read_random)(a, b)
|
||||
#define read_random_uio(a, b) (*_read_random_uio)(a, b)
|
||||
#define is_random_seeded() (*_is_random_seeded)()
|
||||
#else
|
||||
void read_random(void *, u_int);
|
||||
int read_random_uio(struct uio *, bool);
|
||||
bool is_random_seeded(void);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note: if you add or remove members of random_entropy_source, remember to
|
||||
|
Loading…
Reference in New Issue
Block a user