diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c index 38c35086289d..1b8e38bba211 100644 --- a/sys/dev/random/random_harvestq.c +++ b/sys/dev/random/random_harvestq.c @@ -1,4 +1,6 @@ /*- + * Copyright (c) 2017 Oliver Pinter + * Copyright (c) 2017 W. Dean Freeman * Copyright (c) 2000-2015 Mark R V Murray * Copyright (c) 2013 Arthur Mesh * Copyright (c) 2004 Robert N. M. Watson @@ -240,7 +242,27 @@ read_rate_increment(u_int chunk) } /* ARGSUSED */ -RANDOM_CHECK_UINT(harvestmask, 0, RANDOM_HARVEST_EVERYTHING_MASK); +static int +random_check_uint_harvestmask(SYSCTL_HANDLER_ARGS) +{ + int error; + u_int value, orig_value; + + orig_value = value = harvest_context.hc_source_mask; + error = sysctl_handle_int(oidp, &value, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + + if (flsl(value) > ENTROPYSOURCE) + return (EINVAL); + + /* + * Disallow userspace modification of pure entropy sources. + */ + harvest_context.hc_source_mask = (value & ~RANDOM_HARVEST_PURE_MASK) | + (orig_value & RANDOM_HARVEST_PURE_MASK); + return (0); +} /* ARGSUSED */ static int @@ -252,7 +274,7 @@ random_print_harvestmask(SYSCTL_HANDLER_ARGS) error = sysctl_wire_old_buffer(req, 0); if (error == 0) { sbuf_new_for_sysctl(&sbuf, NULL, 128, req); - for (i = RANDOM_ENVIRONMENTAL_END; i >= 0; i--) + for (i = ENTROPYSOURCE - 1; i >= 0; i--) sbuf_cat(&sbuf, (harvest_context.hc_source_mask & (1 << i)) ? "1" : "0"); error = sbuf_finish(&sbuf); sbuf_delete(&sbuf); @@ -272,7 +294,7 @@ static const char *random_source_descr[ENTROPYSOURCE] = { [RANDOM_SWI] = "SWI", [RANDOM_FS_ATIME] = "FS_ATIME", [RANDOM_UMA] = "UMA", /* ENVIRONMENTAL_END */ - [RANDOM_PURE_OCTEON] = "PURE_OCTEON", + [RANDOM_PURE_OCTEON] = "PURE_OCTEON", /* PURE_START */ [RANDOM_PURE_SAFE] = "PURE_SAFE", [RANDOM_PURE_GLXSB] = "PURE_GLXSB", [RANDOM_PURE_UBSEC] = "PURE_UBSEC", @@ -291,15 +313,22 @@ random_print_harvestmask_symbolic(SYSCTL_HANDLER_ARGS) { struct sbuf sbuf; int error, i; + bool first; + first = true; error = sysctl_wire_old_buffer(req, 0); if (error == 0) { sbuf_new_for_sysctl(&sbuf, NULL, 128, req); - for (i = RANDOM_ENVIRONMENTAL_END; i >= 0; i--) { - sbuf_cat(&sbuf, (i == RANDOM_ENVIRONMENTAL_END) ? "" : ","); + for (i = ENTROPYSOURCE - 1; i >= 0; i--) { + if (i >= RANDOM_PURE_START && + (harvest_context.hc_source_mask & (1 << i)) == 0) + continue; + if (!first) + sbuf_cat(&sbuf, ","); sbuf_cat(&sbuf, !(harvest_context.hc_source_mask & (1 << i)) ? "[" : ""); sbuf_cat(&sbuf, random_source_descr[i]); sbuf_cat(&sbuf, !(harvest_context.hc_source_mask & (1 << i)) ? "]" : ""); + first = false; } error = sbuf_finish(&sbuf); sbuf_delete(&sbuf); @@ -321,8 +350,7 @@ random_harvestq_init(void *unused __unused) SYSCTL_ADD_PROC(&random_clist, SYSCTL_CHILDREN(random_sys_o), OID_AUTO, "mask", CTLTYPE_UINT | CTLFLAG_RW, - &harvest_context.hc_source_mask, 0, - random_check_uint_harvestmask, "IU", + NULL, 0, random_check_uint_harvestmask, "IU", "Entropy harvesting mask"); SYSCTL_ADD_PROC(&random_clist, SYSCTL_CHILDREN(random_sys_o), @@ -495,4 +523,18 @@ random_harvest_direct(const void *entropy, u_int size, u_int bits, enum random_e explicit_bzero(&event, sizeof(event)); } +void +random_harvest_register_source(enum random_entropy_source source) +{ + + harvest_context.hc_source_mask |= (1 << source); +} + +void +random_harvest_deregister_source(enum random_entropy_source source) +{ + + harvest_context.hc_source_mask &= ~(1 << source); +} + MODULE_VERSION(random_harvestq, 1); diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c index 7edfca8ad607..28a191f8f7b6 100644 --- a/sys/dev/random/randomdev.c +++ b/sys/dev/random/randomdev.c @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2017 Oliver Pinter * Copyright (c) 2000-2015 Mark R V Murray * All rights reserved. * @@ -321,6 +322,8 @@ random_source_register(struct random_source *rsource) rrs = malloc(sizeof(*rrs), M_ENTROPY, M_WAITOK); rrs->rrs_source = rsource; + random_harvest_register_source(rsource->rs_source); + printf("random: registering fast source %s\n", rsource->rs_ident); LIST_INSERT_HEAD(&source_list, rrs, rrs_entries); } @@ -331,6 +334,9 @@ random_source_deregister(struct random_source *rsource) struct random_sources *rrs = NULL; KASSERT(rsource != NULL, ("invalid input to %s", __func__)); + + random_harvest_deregister_source(rsource->rs_source); + LIST_FOREACH(rrs, &source_list, rrs_entries) if (rrs->rrs_source == rsource) { LIST_REMOVE(rrs, rrs_entries); diff --git a/sys/sys/random.h b/sys/sys/random.h index fb73d1646fb3..9d4a9fb097f7 100644 --- a/sys/sys/random.h +++ b/sys/sys/random.h @@ -81,7 +81,8 @@ enum random_entropy_source { RANDOM_UMA, /* Special!! UMA/SLAB Allocator */ RANDOM_ENVIRONMENTAL_END = RANDOM_UMA, /* Fast hardware random-number sources from here on. */ - RANDOM_PURE_OCTEON, + RANDOM_PURE_START, + RANDOM_PURE_OCTEON = RANDOM_PURE_START, RANDOM_PURE_SAFE, RANDOM_PURE_GLXSB, RANDOM_PURE_UBSEC, @@ -95,6 +96,7 @@ enum random_entropy_source { }; #define RANDOM_HARVEST_EVERYTHING_MASK ((1 << (RANDOM_ENVIRONMENTAL_END + 1)) - 1) +#define RANDOM_HARVEST_PURE_MASK (((1 << ENTROPYSOURCE) - 1) & (-1UL << RANDOM_PURE_START)) #define RANDOM_LEGACY_BOOT_ENTROPY_MODULE "/boot/entropy" #define RANDOM_CACHED_BOOT_ENTROPY_MODULE "boot_entropy_cache" @@ -104,10 +106,14 @@ enum random_entropy_source { void random_harvest_queue(const void *, u_int, u_int, enum random_entropy_source); void random_harvest_fast(const void *, u_int, u_int, enum random_entropy_source); void random_harvest_direct(const void *, u_int, u_int, enum random_entropy_source); +void random_harvest_register_source(enum random_entropy_source); +void random_harvest_deregister_source(enum random_entropy_source); #else #define random_harvest_queue(a, b, c, d) do {} while (0) #define random_harvest_fast(a, b, c, d) do {} while (0) #define random_harvest_direct(a, b, c, d) do {} while (0) +#define random_harvest_register_source(a) do {} while (0) +#define random_harvest_deregister_source(a) do {} while (0) #endif #if defined(RANDOM_ENABLE_UMA)