From bd251de035cd1a925007b605d05ecf05b3ef698f Mon Sep 17 00:00:00 2001 From: Tony Finch Date: Fri, 22 Apr 2022 14:35:36 +0100 Subject: [PATCH] Move random number re-seeding out of the hot path Instead of checking if we need to re-seed for every isc_random call, seed the random number generator in the libisc global initializer and the per-thread initializer. --- lib/isc/Makefile.am | 1 + lib/isc/random.c | 20 +++----------------- lib/isc/random_p.h | 30 ++++++++++++++++++++++++++++++ lib/isc/trampoline.c | 9 +++++++++ tests/isc/random_test.c | 8 ++++++++ 5 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 lib/isc/random_p.h diff --git a/lib/isc/Makefile.am b/lib/isc/Makefile.am index adc147b968..c23ebf3138 100644 --- a/lib/isc/Makefile.am +++ b/lib/isc/Makefile.am @@ -180,6 +180,7 @@ libisc_la_SOURCES = \ quota.c \ radix.c \ random.c \ + random_p.h \ ratelimiter.c \ regex.c \ region.c \ diff --git a/lib/isc/random.c b/lib/isc/random.c index 842f4e4fe3..8f804360db 100644 --- a/lib/isc/random.c +++ b/lib/isc/random.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include @@ -43,6 +42,7 @@ #include #include "entropy_private.h" +#include "random_p.h" /* * Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) @@ -88,11 +88,8 @@ next(void) { return (result_starstar); } - -static thread_local isc_once_t isc_random_once = ISC_ONCE_INIT; - -static void -isc_random_initialize(void) { +void +isc__random_initialize(void) { int useed[4] = { 0, 0, 0, 1 }; #if FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION /* @@ -108,22 +105,16 @@ isc_random_initialize(void) { uint8_t isc_random8(void) { - RUNTIME_CHECK(isc_once_do(&isc_random_once, isc_random_initialize) == - ISC_R_SUCCESS); return ((uint8_t)next()); } uint16_t isc_random16(void) { - RUNTIME_CHECK(isc_once_do(&isc_random_once, isc_random_initialize) == - ISC_R_SUCCESS); return ((uint16_t)next()); } uint32_t isc_random32(void) { - RUNTIME_CHECK(isc_once_do(&isc_random_once, isc_random_initialize) == - ISC_R_SUCCESS); return (next()); } @@ -135,9 +126,6 @@ isc_random_buf(void *buf, size_t buflen) { REQUIRE(buf != NULL); REQUIRE(buflen > 0); - RUNTIME_CHECK(isc_once_do(&isc_random_once, isc_random_initialize) == - ISC_R_SUCCESS); - for (i = 0; i + sizeof(r) <= buflen; i += sizeof(r)) { r = next(); memmove((uint8_t *)buf + i, &r, sizeof(r)); @@ -149,8 +137,6 @@ isc_random_buf(void *buf, size_t buflen) { uint32_t isc_random_uniform(uint32_t limit) { - RUNTIME_CHECK(isc_once_do(&isc_random_once, isc_random_initialize) == - ISC_R_SUCCESS); /* * Daniel Lemire's nearly-divisionless unbiased bounded random numbers. * diff --git a/lib/isc/random_p.h b/lib/isc/random_p.h new file mode 100644 index 0000000000..3e4917f8b7 --- /dev/null +++ b/lib/isc/random_p.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#pragma once + +#include + +/*! \file isc/random_p.h + * \brief For automatically seeding and re-seeding when required. + */ + +ISC_LANG_BEGINDECLS + +void +isc__random_initialize(void); +/*!< + * \brief Seed the thread-local random number state with fresh entropy. + */ + +ISC_LANG_ENDDECLS diff --git a/lib/isc/trampoline.c b/lib/isc/trampoline.c index b724b74450..c862ba37b0 100644 --- a/lib/isc/trampoline.c +++ b/lib/isc/trampoline.c @@ -22,6 +22,7 @@ #include #include +#include "random_p.h" #include "trampoline_p.h" #define ISC__TRAMPOLINE_UNUSED 0 @@ -87,6 +88,8 @@ isc__trampoline_initialize(void) { trampolines[i] = NULL; } isc__trampoline_min = 1; + + isc__random_initialize(); } void @@ -175,6 +178,12 @@ isc__trampoline_attach(isc__trampoline_t *trampoline) { * malloc() + free() calls altogether, as it would foil the fix. */ trampoline->jemalloc_enforce_init = malloc(8); + + /* + * Re-seed the random number generator in each thread. + */ + isc__random_initialize(); + uv_mutex_unlock(&isc__trampoline_lock); } diff --git a/tests/isc/random_test.c b/tests/isc/random_test.c index 8c41e97138..1651dbba74 100644 --- a/tests/isc/random_test.c +++ b/tests/isc/random_test.c @@ -640,6 +640,13 @@ binarymatrixrank(uint16_t *values, size_t length) { *** Tests for isc_random32() function ***/ +/* Ensure the RNG has been automatically seeded. */ +ISC_RUN_TEST_IMPL(isc_random32_initialized) { + UNUSED(state); + + assert_int_not_equal(isc_random32(), 0); +} + /* Monobit test for the RANDOM */ ISC_RUN_TEST_IMPL(isc_random32_monobit) { UNUSED(state); @@ -764,6 +771,7 @@ ISC_RUN_TEST_IMPL(isc_nonce_bytes_binarymatrixrank) { ISC_TEST_LIST_START +ISC_TEST_ENTRY(isc_random32_initialized) ISC_TEST_ENTRY(isc_random32_monobit) ISC_TEST_ENTRY(isc_random32_runs) ISC_TEST_ENTRY(isc_random32_blockfrequency)