Index: head/UPDATING =================================================================== --- head/UPDATING +++ head/UPDATING @@ -26,6 +26,9 @@ 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 Index: head/sys/dev/random/fortuna.c =================================================================== --- head/sys/dev/random/fortuna.c +++ head/sys/dev/random/fortuna.c @@ -261,15 +261,14 @@ 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 @@ 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 @@ 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() Index: head/sys/dev/random/other_algorithm.c =================================================================== --- head/sys/dev/random/other_algorithm.c +++ head/sys/dev/random/other_algorithm.c @@ -87,8 +87,6 @@ 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 @@ */ #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 @@ 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) Index: head/sys/dev/random/random_harvestq.c =================================================================== --- head/sys/dev/random/random_harvestq.c +++ head/sys/dev/random/random_harvestq.c @@ -49,11 +49,6 @@ #include #include -#if defined(RANDOM_LOADABLE) -#include -#include -#endif - #include #include @@ -163,14 +158,7 @@ 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 @@ * 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 @@ } } explicit_bzero(entropy, sizeof(entropy)); -#if defined(RANDOM_LOADABLE) - } - RANDOM_CONFIG_S_UNLOCK(); -#endif } void @@ -396,7 +375,7 @@ 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 @@ 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. Index: head/sys/dev/random/random_infra.c =================================================================== --- head/sys/dev/random/random_infra.c +++ head/sys/dev/random/random_infra.c @@ -35,11 +35,6 @@ #include #include -#if defined(RANDOM_LOADABLE) -#include -#include -#endif - #include /* Set up the sysctl root node for the entropy device */ @@ -102,107 +97,8 @@ 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) */ Index: head/sys/dev/random/randomdev.h =================================================================== --- head/sys/dev/random/randomdev.h +++ head/sys/dev/random/randomdev.h @@ -79,15 +79,18 @@ 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 @@ 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 */ Index: head/sys/dev/random/randomdev.c =================================================================== --- head/sys/dev/random/randomdev.c +++ head/sys/dev/random/randomdev.c @@ -59,17 +59,17 @@ #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 @@ /* 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 @@ 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 @@ 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 @@ } 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 @@ */ 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 @@ * '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 @@ } bool -IS_RANDOM_SEEDED(void) +(is_random_seeded)(void) { return (p_random_alg_context->ra_seeded()); } @@ -356,7 +343,7 @@ 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 @@ { 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 @@ make_dev_alias(random_dev, "urandom"); /* compatibility */ break; case MOD_UNLOAD: - destroy_dev(random_dev); + error = EBUSY; break; case MOD_SHUTDOWN: break; Index: head/sys/sys/random.h =================================================================== --- head/sys/sys/random.h +++ head/sys/sys/random.h @@ -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