From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753246AbbJPF3O (ORCPT ); Fri, 16 Oct 2015 01:29:14 -0400 Received: from ns.horizon.com ([71.41.210.147]:64190 "HELO ns.horizon.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1752735AbbJPF3N (ORCPT ); Fri, 16 Oct 2015 01:29:13 -0400 Date: 16 Oct 2015 01:29:11 -0400 Message-ID: <20151016052911.12487.qmail@ns.horizon.com> From: "George Spelvin" To: andi@firstfloor.org, tytso@mit.edu Subject: [RFC PATCH 1/4] random: Reduce stack usage in _xfer_secondary_pool Cc: ahferroin7@gmail.com, jepler@unpythonic.net, linux-kernel@vger.kernel.org, linux@horizon.com, linux@rasmusvillemoes.dk In-Reply-To: <20151016052802.12363.qmail@ns.horizon.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Rather than asking extract_entropy to fill a large buffer, transfer bytes in EXTRACT_SIZE chunks using multiple calls to extract_buf. (Which is what extract_entropy does internally.) Signed-off-by: George Spelvin --- drivers/char/random.c | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index d0da5d85..c8ad49ba 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -964,8 +964,9 @@ EXPORT_SYMBOL_GPL(add_disk_randomness); * *********************************************************************/ -static ssize_t extract_entropy(struct entropy_store *r, void *buf, - size_t nbytes, int min, int rsvd); +static size_t account(struct entropy_store *r, size_t nbytes, int min, + int reserved); +static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE]); /* * This utility inline function is responsible for transferring entropy @@ -994,23 +995,46 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes) { - __u32 tmp[OUTPUT_POOL_WORDS]; - - /* For /dev/random's pool, always leave two wakeups' worth */ - int rsvd_bytes = r->limit ? 0 : random_read_wakeup_bits / 4; + u8 tmp[EXTRACT_SIZE]; int bytes = nbytes; /* pull at least as much as a wakeup */ bytes = max_t(int, bytes, random_read_wakeup_bits / 8); /* but never more than the buffer size */ - bytes = min_t(int, bytes, sizeof(tmp)); + bytes = min_t(int, bytes, OUTPUT_POOL_WORDS*sizeof(u32)); + /* + * FIXME: Move this to after account(), so it shows the true amount + * transferred? + */ trace_xfer_secondary_pool(r->name, bytes * 8, nbytes * 8, ENTROPY_BITS(r), ENTROPY_BITS(r->pull)); - bytes = extract_entropy(r->pull, tmp, bytes, - random_read_wakeup_bits / 8, rsvd_bytes); - mix_pool_bytes(r, tmp, bytes); - credit_entropy_bits(r, bytes*8); + + /* + * This is the only place we call account() with non-zero + * "min" and "reserved" values. The minimum is used to + * enforce catastrophic reseeding: if we can't get at least + * random_read_wakeup_bits of entropy, don't bother reseeding + * at all, but wait until a useful amount is available. + * + * The "reserved" is used to prevent reads from /dev/urandom + * from emptying the unput pool; leave two wakeups' worth + * for /dev/random. + */ + bytes = account(r->pull, bytes, random_read_wakeup_bits / 8, + r->limit ? 0 : random_read_wakeup_bits / 4); + + /* Now to the actual transfer, in EXTRACT_SIZE units */ + while (bytes) { + int i = min_t(int, bytes, EXTRACT_SIZE); + + extract_buf(r->pull, tmp); + mix_pool_bytes(r, tmp, i); + credit_entropy_bits(r, i*8); + bytes -= i; + } + + memzero_explicit(tmp, sizeof(tmp)); } /* @@ -1087,7 +1111,7 @@ retry: * * Note: we assume that .poolwords is a multiple of 16 words. */ -static void extract_buf(struct entropy_store *r, __u8 *out) +static void extract_buf(struct entropy_store *r, __u8 out[EXTRACT_SIZE]) { int i; union { -- 2.6.1