From f3d2512db6ec23985b10fbcbe0b3bd34ea2574df Mon Sep 17 00:00:00 2001 From: Conrad Meyer Date: Tue, 16 Apr 2019 17:12:17 +0000 Subject: [PATCH] random(4): Add is_random_seeded(9) KPI The imagined use is for early boot consumers of random to be able to make decisions based on whether random is available yet or not. One such consumer seems to be __stack_chk_init(), which runs immediately after random is initialized. A follow-up patch will attempt to address that. Reported by: many Reviewed by: delphij (except man page) Approved by: secteam(delphij) Differential Revision: https://reviews.freebsd.org/D19926 --- UPDATING | 6 ++++++ share/man/man9/Makefile | 1 + share/man/man9/random.9 | 12 +++++++++++- sys/dev/random/random_infra.c | 23 ++++++++++++++++++++++- sys/dev/random/randomdev.c | 11 ++++++++++- sys/dev/random/randomdev.h | 3 ++- sys/sys/param.h | 2 +- sys/sys/random.h | 6 ++++++ 8 files changed, 59 insertions(+), 5 deletions(-) diff --git a/UPDATING b/UPDATING index a4864d1b45d5..d909a17396b0 100644 --- a/UPDATING +++ b/UPDATING @@ -31,6 +31,12 @@ 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".) +20190416: + The loadable random module KPI has changed; the random_infra_init() + routine now requires a 3rd function pointer for a bool (*)(void) + method that returns true if the random device is seeded (and + therefore unblocked). + 20190404: r345895 reverts r320698. This implies that an nfsuserd(8) daemon built from head sources between r320757 (July 6, 2017) and diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 6eb5ee9e7983..863a1135f5a6 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -1668,6 +1668,7 @@ MLINKS+=psignal.9 gsignal.9 \ psignal.9 tdsignal.9 MLINKS+=random.9 arc4rand.9 \ random.9 arc4random.9 \ + random.9 is_random_seeded.9 \ random.9 read_random.9 \ random.9 read_random_uio.9 \ random.9 srandom.9 diff --git a/share/man/man9/random.9 b/share/man/man9/random.9 index 2e6189790412..97218dcab39c 100644 --- a/share/man/man9/random.9 +++ b/share/man/man9/random.9 @@ -26,13 +26,14 @@ .\" .\" $FreeBSD$ .\" " -.Dd April 15, 2019 +.Dd April 16, 2019 .Dt RANDOM 9 .Os .Sh NAME .Nm arc4rand , .Nm arc4random , .Nm arc4random_buf , +.Nm is_random_seeded , .Nm random , .Nm read_random , .Nm read_random_uio , @@ -48,6 +49,8 @@ .Fn arc4rand "void *ptr" "u_int length" "int reseed" .Pp .In sys/random.h +.Ft bool +.Fn is_random_seeded "void" .Ft void .Fn read_random "void *buffer" "int count" .Ft int @@ -108,6 +111,13 @@ instead, use the family of functions. .Pp The +.Fn is_random_seeded +function can be used to check in advance if +.Fn read_random +will block. +(If random is seeded, it will not block.) +.Pp +The .Fn read_random_uio function behaves identically to .Xr read 2 diff --git a/sys/dev/random/random_infra.c b/sys/dev/random/random_infra.c index 324c40dcecd4..59cd44280b95 100644 --- a/sys/dev/random/random_infra.c +++ b/sys/dev/random/random_infra.c @@ -63,12 +63,20 @@ 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; @@ -82,12 +90,15 @@ random_infra_sysinit(void *dummy __unused) 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)) +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(); } @@ -98,6 +109,7 @@ 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(); } @@ -129,4 +141,13 @@ read_random(void *buf, u_int len) RANDOM_CONFIG_S_UNLOCK(); } +bool +is_random_seeded(void) +{ + RANDOM_CONFIG_S_LOCK(); + random_reader_context.is_random_seeded(); + RANDOM_CONFIG_S_UNLOCK(); +} + + #endif /* defined(RANDOM_LOADABLE) */ diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c index 19a73b28151a..cbe01d1c5343 100644 --- a/sys/dev/random/randomdev.c +++ b/sys/dev/random/randomdev.c @@ -62,11 +62,14 @@ __FBSDID("$FreeBSD$"); #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 #endif static d_read_t randomdev_read; @@ -93,7 +96,7 @@ 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); + random_infra_init(READ_RANDOM_UIO, READ_RANDOM, IS_RANDOM_SEEDED); #endif } @@ -271,6 +274,12 @@ READ_RANDOM(void *random_buf, u_int len) } } +bool +IS_RANDOM_SEEDED(void) +{ + return (p_random_alg_context->ra_seeded()); +} + static __inline void randomdev_accumulate(uint8_t *buf, u_int count) { diff --git a/sys/dev/random/randomdev.h b/sys/dev/random/randomdev.h index 41300f237aaf..e5df7efefa5b 100644 --- a/sys/dev/random/randomdev.h +++ b/sys/dev/random/randomdev.h @@ -118,7 +118,8 @@ extern struct sx 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)); +void random_infra_init(int (*)(struct uio *, bool), void (*)(void *, u_int), + bool (*)(void)); void random_infra_uninit(void); #endif diff --git a/sys/sys/param.h b/sys/sys/param.h index 8dc3686027bd..ddc59bf64373 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -60,7 +60,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 1300018 /* Master, propagated to newvers */ +#define __FreeBSD_version 1300019 /* Master, propagated to newvers */ /* * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD, diff --git a/sys/sys/random.h b/sys/sys/random.h index 8a9cbf49ccbd..aa8c5f02c32e 100644 --- a/sys/sys/random.h +++ b/sys/sys/random.h @@ -40,6 +40,7 @@ struct uio; #if defined(DEV_RANDOM) void read_random(void *, u_int); int read_random_uio(struct uio *, bool); +bool is_random_seeded(void); #else static __inline int read_random_uio(void *a __unused, u_int b __unused) @@ -50,6 +51,11 @@ static __inline void read_random(void *a __unused, u_int b __unused) { } +static __inline bool +is_random_seeded(void) +{ + return (false); +} #endif /*