Date: Thu, 26 Dec 2019 19:32:11 +0000 (UTC) From: Conrad Meyer <cem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r356096 - in head: . sys/dev/random sys/sys Message-ID: <201912261932.xBQJWBbH052389@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: cem Date: Thu Dec 26 19:32:11 2019 New Revision: 356096 URL: https://svnweb.freebsd.org/changeset/base/356096 Log: 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 Modified: head/UPDATING head/sys/dev/random/fortuna.c head/sys/dev/random/other_algorithm.c head/sys/dev/random/random_harvestq.c head/sys/dev/random/random_infra.c head/sys/dev/random/randomdev.c head/sys/dev/random/randomdev.h head/sys/sys/random.h Modified: head/UPDATING ============================================================================== --- head/UPDATING Thu Dec 26 18:59:43 2019 (r356095) +++ head/UPDATING Thu Dec 26 19:32:11 2019 (r356096) @@ -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 Modified: head/sys/dev/random/fortuna.c ============================================================================== --- head/sys/dev/random/fortuna.c Thu Dec 26 18:59:43 2019 (r356095) +++ head/sys/dev/random/fortuna.c Thu Dec 26 19:32:11 2019 (r356096) @@ -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() Modified: head/sys/dev/random/other_algorithm.c ============================================================================== --- head/sys/dev/random/other_algorithm.c Thu Dec 26 18:59:43 2019 (r356095) +++ head/sys/dev/random/other_algorithm.c Thu Dec 26 19:32:11 2019 (r356096) @@ -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) Modified: head/sys/dev/random/random_harvestq.c ============================================================================== --- head/sys/dev/random/random_harvestq.c Thu Dec 26 18:59:43 2019 (r356095) +++ head/sys/dev/random/random_harvestq.c Thu Dec 26 19:32:11 2019 (r356096) @@ -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. Modified: head/sys/dev/random/random_infra.c ============================================================================== --- head/sys/dev/random/random_infra.c Thu Dec 26 18:59:43 2019 (r356095) +++ head/sys/dev/random/random_infra.c Thu Dec 26 19:32:11 2019 (r356096) @@ -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) */ Modified: head/sys/dev/random/randomdev.c ============================================================================== --- head/sys/dev/random/randomdev.c Thu Dec 26 18:59:43 2019 (r356095) +++ head/sys/dev/random/randomdev.c Thu Dec 26 19:32:11 2019 (r356096) @@ -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,31 +89,18 @@ 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_SECOND, random_alg_context_init, + NULL); +#endif -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); - 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 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, vo make_dev_alias(random_dev, "urandom"); /* compatibility */ break; case MOD_UNLOAD: - destroy_dev(random_dev); + error = EBUSY; break; case MOD_SHUTDOWN: break; Modified: head/sys/dev/random/randomdev.h ============================================================================== --- head/sys/dev/random/randomdev.h Thu Dec 26 18:59:43 2019 (r356095) +++ head/sys/dev/random/randomdev.h Thu Dec 26 19:32:11 2019 (r356096) @@ -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 @@ -104,19 +107,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 */ Modified: head/sys/sys/random.h ============================================================================== --- head/sys/sys/random.h Thu Dec 26 18:59:43 2019 (r356095) +++ head/sys/sys/random.h Thu Dec 26 19:32:11 2019 (r356096) @@ -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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201912261932.xBQJWBbH052389>