Make the UMA harvesting go away completely if not wanted. Default to "not wanted".

Provide and document the RANDOM_ENABLE_UMA option.

Change RANDOM_FAST to RANDOM_UMA to clarify the harvesting.

Remove RANDOM_DEBUG option, replace with SDT probes. These will be of
use to folks measuring the harvesting effect when deciding whether to
use RANDOM_ENABLE_UMA.

Requested by:	scottl and others.
Approved by:	so (/dev/random blanket)
Differential Revision:    https://reviews.freebsd.org/D3197
This commit is contained in:
Mark Murray 2015-08-22 12:59:05 +00:00
parent 1bb0c0bd8d
commit e866d8f05b
10 changed files with 61 additions and 43 deletions

@ -32,6 +32,7 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Cd "device random" .Cd "device random"
.Cd "options RANDOM_LOADABLE" .Cd "options RANDOM_LOADABLE"
.Cd "options RANDOM_ENABLE_UMA"
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Nm .Nm
@ -177,6 +178,24 @@ must be locked against
load and unload events, load and unload events,
and also must be indirect calls and also must be indirect calls
to allow for removal. to allow for removal.
.Pp
When
.Cd "options RANDOM_ENABLE_UMA"
is used,
the
.Pa /dev/random
device will obtain entropy
from the zone allocator.
This is potentially very high rate,
and if so will be of questionable use.
If this is the case,
use of this option
is not recommended.
Determining this is not trivial,
so experimenting and measurement
using tools such as
.Xr dtrace 1
will be required.
.Sh RANDOMNESS .Sh RANDOMNESS
The use of randomness in the field of computing The use of randomness in the field of computing
is a rather subtle issue because randomness means is a rather subtle issue because randomness means

@ -2985,8 +2985,10 @@ options MAXFILES=999
#options RANDOM_YARROW # Yarrow CSPRNG (old default) #options RANDOM_YARROW # Yarrow CSPRNG (old default)
#options RANDOM_LOADABLE # Allow the algorithm to be loaded as #options RANDOM_LOADABLE # Allow the algorithm to be loaded as
# a module. # a module.
# For developers. # Select this to allow high-rate but potentially expensive
options RANDOM_DEBUG # Extra debugging messages # harvesting of Slab-Allocator entropy. In very high-rate
# situations the value of doing this is dubious at best.
options RANDOM_ENABLE_UMA # slab allocator
# Module to enable execution of application via emulators like QEMU # Module to enable execution of application via emulators like QEMU
options IMAGACT_BINMISC options IMAGACT_BINMISC

@ -945,17 +945,16 @@ RACCT_DEFAULT_TO_DISABLED opt_global.h
RCTL opt_global.h RCTL opt_global.h
# Random number generator(s) # Random number generator(s)
# The DEBUG option is in global.h as the random harvesting # Which CSPRNG hash we get.
# puts probes all over the place, and it makes little sense
# to pollute these headers with an extra include.
RANDOM_DEBUG opt_random.h
# Which CSPRNG hashes we get.
# If Yarrow is not chosen, Fortuna is selected. # If Yarrow is not chosen, Fortuna is selected.
RANDOM_YARROW opt_random.h RANDOM_YARROW opt_random.h
# With this, no entropy processor is loaded, but the entropy # With this, no entropy processor is loaded, but the entropy
# harvesting infrastructure is present. This means an entropy # harvesting infrastructure is present. This means an entropy
# processor may be loaded as a module. # processor may be loaded as a module.
RANDOM_LOADABLE opt_random.h RANDOM_LOADABLE opt_random.h
# This turns on high-rate and potentially expensive harvesting in
# the uma slab allocator.
RANDOM_ENABLE_UMA opt_global.h
# Intel em(4) driver # Intel em(4) driver
EM_MULTIQUEUE opt_em.h EM_MULTIQUEUE opt_em.h

@ -35,7 +35,7 @@
# <(sed -e 's/fortuna/wombat/g' \ # <(sed -e 's/fortuna/wombat/g' \
# -e 's/FORTUNA/WOMBAT/g' fortuna.c) | less # -e 's/FORTUNA/WOMBAT/g' fortuna.c) | less
# #
cc -g -O0 -pthread -DRANDOM_DEBUG \ cc -g -O0 -pthread \
-I../.. -lstdthreads -Wall \ -I../.. -lstdthreads -Wall \
unit_test.c \ unit_test.c \
yarrow.c \ yarrow.c \
@ -46,7 +46,7 @@ cc -g -O0 -pthread -DRANDOM_DEBUG \
../../crypto/sha2/sha256c.c \ ../../crypto/sha2/sha256c.c \
-lz \ -lz \
-o yunit_test -o yunit_test
cc -g -O0 -pthread -DRANDOM_DEBUG \ cc -g -O0 -pthread \
-I../.. -lstdthreads -Wall \ -I../.. -lstdthreads -Wall \
unit_test.c \ unit_test.c \
fortuna.c \ fortuna.c \

@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/random.h> #include <sys/random.h>
#include <sys/sdt.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -94,6 +95,11 @@ CTASSERT(RANDOM_FORTUNA_DEFPOOLSIZE <= RANDOM_FORTUNA_MAXPOOLSIZE);
CTASSERT(RANDOM_BLOCKSIZE == sizeof(uint128_t)); CTASSERT(RANDOM_BLOCKSIZE == sizeof(uint128_t));
CTASSERT(RANDOM_KEYSIZE == 2*RANDOM_BLOCKSIZE); CTASSERT(RANDOM_KEYSIZE == 2*RANDOM_BLOCKSIZE);
/* Probes for dtrace(1) */
SDT_PROVIDER_DECLARE(random);
SDT_PROVIDER_DEFINE(random);
SDT_PROBE_DEFINE2(random, fortuna, event_processor, debug, "u_int", "struct fs_pool *");
/* /*
* This is the beastie that needs protecting. It contains all of the * This is the beastie that needs protecting. It contains all of the
* state that we are excited about. Exactly one is instantiated. * state that we are excited about. Exactly one is instantiated.
@ -379,16 +385,7 @@ random_fortuna_pre_read(void)
} else } else
break; break;
} }
#ifdef RANDOM_DEBUG SDT_PROBE2(random, fortuna, event_processor, debug, fortuna_state.fs_reseedcount, fortuna_state.fs_pool);
{
u_int j;
printf("random: reseedcount [%d]", fortuna_state.fs_reseedcount);
for (j = 0; j < RANDOM_FORTUNA_NPOOLS; j++)
printf(" %X", fortuna_state.fs_pool[j].fsp_length);
printf("\n");
}
#endif
/* FS&K */ /* FS&K */
random_fortuna_reseed_internal(s, i < RANDOM_FORTUNA_NPOOLS ? i + 1 : RANDOM_FORTUNA_NPOOLS); random_fortuna_reseed_internal(s, i < RANDOM_FORTUNA_NPOOLS ? i + 1 : RANDOM_FORTUNA_NPOOLS);
/* Clean up and secure */ /* Clean up and secure */

@ -170,7 +170,7 @@ random_kthread(void)
/* XXX: FIX!! Increase the high-performance data rate? Need some measurements first. */ /* XXX: FIX!! Increase the high-performance data rate? Need some measurements first. */
for (i = 0; i < RANDOM_ACCUM_MAX; i++) { for (i = 0; i < RANDOM_ACCUM_MAX; i++) {
if (harvest_context.hc_entropy_fast_accumulator.buf[i]) { if (harvest_context.hc_entropy_fast_accumulator.buf[i]) {
random_harvest_direct(harvest_context.hc_entropy_fast_accumulator.buf + i, sizeof(harvest_context.hc_entropy_fast_accumulator.buf[0]), 4, RANDOM_FAST); random_harvest_direct(harvest_context.hc_entropy_fast_accumulator.buf + i, sizeof(harvest_context.hc_entropy_fast_accumulator.buf[0]), 4, RANDOM_UMA);
harvest_context.hc_entropy_fast_accumulator.buf[i] = 0; harvest_context.hc_entropy_fast_accumulator.buf[i] = 0;
} }
} }
@ -261,7 +261,7 @@ static const char *(random_source_descr[]) = {
"INTERRUPT", "INTERRUPT",
"SWI", "SWI",
"FS_ATIME", "FS_ATIME",
"HIGH_PERFORMANCE", /* ENVIRONMENTAL_END */ "UMA", /* ENVIRONMENTAL_END */
"PURE_OCTEON", "PURE_OCTEON",
"PURE_SAFE", "PURE_SAFE",
"PURE_GLXSB", "PURE_GLXSB",

@ -29,7 +29,7 @@
/* /*
Build this by going: Build this by going:
cc -g -O0 -pthread -DRANDOM_<alg> -DRANDOM_DEBUG -I../.. -lstdthreads -Wall \ cc -g -O0 -pthread -DRANDOM_<alg> -I../.. -lstdthreads -Wall \
unit_test.c \ unit_test.c \
yarrow.c \ yarrow.c \
fortuna.c \ fortuna.c \

@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/random.h> #include <sys/random.h>
#include <sys/sdt.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -77,6 +78,11 @@ __FBSDID("$FreeBSD$");
CTASSERT(RANDOM_BLOCKSIZE == sizeof(uint128_t)); CTASSERT(RANDOM_BLOCKSIZE == sizeof(uint128_t));
CTASSERT(RANDOM_KEYSIZE == 2*RANDOM_BLOCKSIZE); CTASSERT(RANDOM_KEYSIZE == 2*RANDOM_BLOCKSIZE);
/* Probes for dtrace(1) */
SDT_PROVIDER_DECLARE(random);
SDT_PROVIDER_DEFINE(random);
SDT_PROBE_DEFINE3(random, yarrow, event_processor, debug, "boolean", "u_int", "struct ys_pool *");
/* /*
* This is the beastie that needs protecting. It contains all of the * This is the beastie that needs protecting. It contains all of the
* state that we are excited about. Exactly one is instantiated. * state that we are excited about. Exactly one is instantiated.
@ -261,20 +267,7 @@ random_yarrow_reseed_internal(u_int fastslow)
KASSERT(yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_thresh > 0, ("random: Yarrow fast threshold = 0")); KASSERT(yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_thresh > 0, ("random: Yarrow fast threshold = 0"));
KASSERT(yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_thresh > 0, ("random: Yarrow slow threshold = 0")); KASSERT(yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_thresh > 0, ("random: Yarrow slow threshold = 0"));
RANDOM_RESEED_ASSERT_LOCK_OWNED(); RANDOM_RESEED_ASSERT_LOCK_OWNED();
#ifdef RANDOM_DEBUG SDT_PROBE3(random, yarrow, event_processor, debug, yarrow_state.ys_seeded, yarrow_state.ys_slowoverthresh, yarrow_state.ys_pool);
/* WARNING! This is dangerously tedious to do with mutexes held! */
printf("random: %s ", __func__);
printf("type/pool = %s ", fastslow == RANDOM_YARROW_FAST ? "RANDOM_YARROW_FAST" : "RANDOM_YARROW_SLOW");
printf("seeded = %s\n", yarrow_state.ys_seeded ? "true" : "false");
printf("random: fast - thresh %d,1 - ", yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_thresh);
for (i = RANDOM_START; i < ENTROPYSOURCE; i++)
printf(" %d", yarrow_state.ys_pool[RANDOM_YARROW_FAST].ysp_source_bits[i]);
printf("\n");
printf("random: slow - thresh %d,%d - ", yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_thresh, yarrow_state.ys_slowoverthresh);
for (i = RANDOM_START; i < ENTROPYSOURCE; i++)
printf(" %d", yarrow_state.ys_pool[RANDOM_YARROW_SLOW].ysp_source_bits[i]);
printf("\n");
#endif
/* 1. Hash the accumulated entropy into v[0] */ /* 1. Hash the accumulated entropy into v[0] */
randomdev_hash_init(&context); randomdev_hash_init(&context);
/* Feed the slow pool hash in if slow */ /* Feed the slow pool hash in if slow */

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2000-2013 Mark R. V. Murray * Copyright (c) 2000-2015 Mark R. V. Murray
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -35,9 +35,11 @@
#include "opt_random.h" #include "opt_random.h"
#if !defined(KLD_MODULE)
#if defined(RANDOM_LOADABLE) && defined(RANDOM_YARROW) #if defined(RANDOM_LOADABLE) && defined(RANDOM_YARROW)
#error "Cannot define both RANDOM_LOADABLE and RANDOM_YARROW" #error "Cannot define both RANDOM_LOADABLE and RANDOM_YARROW"
#endif #endif
#endif
struct uio; struct uio;
@ -78,8 +80,8 @@ enum random_entropy_source {
RANDOM_INTERRUPT, RANDOM_INTERRUPT,
RANDOM_SWI, RANDOM_SWI,
RANDOM_FS_ATIME, RANDOM_FS_ATIME,
RANDOM_FAST, /* Special!! Miscellaneous high performance stuff, like UMA/SLAB Allocator */ RANDOM_UMA, /* Special!! UMA/SLAB Allocator */
RANDOM_ENVIRONMENTAL_END = RANDOM_FAST, RANDOM_ENVIRONMENTAL_END = RANDOM_UMA,
/* Fast hardware random-number sources from here on. */ /* Fast hardware random-number sources from here on. */
RANDOM_PURE_OCTEON, RANDOM_PURE_OCTEON,
RANDOM_PURE_SAFE, RANDOM_PURE_SAFE,
@ -105,6 +107,12 @@ void random_harvest_direct(const void *, u_int, u_int, enum random_entropy_sourc
#define random_harvest_direct(a, b, c, d) do {} while (0) #define random_harvest_direct(a, b, c, d) do {} while (0)
#endif #endif
#if defined(RANDOM_ENABLE_UMA)
#define random_harvest_fast_uma(a, b, c, d) random_harvest_fast(a, b, c, d)
#else /* !defined(RANDOM_ENABLE_UMA) */
#define random_harvest_fast_uma(a, b, c, d) do {} while (0)
#endif /* defined(RANDOM_ENABLE_UMA) */
#endif /* _KERNEL */ #endif /* _KERNEL */
#endif /* _SYS_RANDOM_H_ */ #endif /* _SYS_RANDOM_H_ */

@ -2135,8 +2135,8 @@ uma_zalloc_arg(uma_zone_t zone, void *udata, int flags)
int lockfail; int lockfail;
int cpu; int cpu;
/* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */ /* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */
random_harvest_fast(&zone, sizeof(zone), 1, RANDOM_FAST); random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA);
/* This is the fast path allocation */ /* This is the fast path allocation */
#ifdef UMA_DEBUG_ALLOC_1 #ifdef UMA_DEBUG_ALLOC_1
@ -2677,8 +2677,8 @@ uma_zfree_arg(uma_zone_t zone, void *item, void *udata)
int lockfail; int lockfail;
int cpu; int cpu;
/* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */ /* Enable entropy collection for RANDOM_ENABLE_UMA kernel option */
random_harvest_fast(&zone, sizeof(zone), 1, RANDOM_FAST); random_harvest_fast_uma(&zone, sizeof(zone), 1, RANDOM_UMA);
#ifdef UMA_DEBUG_ALLOC_1 #ifdef UMA_DEBUG_ALLOC_1
printf("Freeing item %p to %s(%p)\n", item, zone->uz_name, zone); printf("Freeing item %p to %s(%p)\n", item, zone->uz_name, zone);