From patchwork Thu Jul 17 18:22:17 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 4578111 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 434459F26C for ; Thu, 17 Jul 2014 18:23:49 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6BC882011E for ; Thu, 17 Jul 2014 18:23:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7F4D620117 for ; Thu, 17 Jul 2014 18:23:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754835AbaGQSWi (ORCPT ); Thu, 17 Jul 2014 14:22:38 -0400 Received: from mail-pd0-f172.google.com ([209.85.192.172]:60091 "EHLO mail-pd0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754468AbaGQSWf (ORCPT ); Thu, 17 Jul 2014 14:22:35 -0400 Received: by mail-pd0-f172.google.com with SMTP id ft15so3577777pdb.17 for ; Thu, 17 Jul 2014 11:22:34 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=iHMqJzejvMaSrUJ/rTTOqDefZQ9V+EH0GKxWPFq8nG0=; b=MBXOC0QxZJqpHIuMt9VbbTE/H4LMXK5xxP/en10J6CSqRfH+0jNEPi1wsmAyLt/E1n nCle8Vr2jAkbQI7bWiI9JJ9K75mKhD5Y3U+hVqGpqw4JPrkStstBJwPiiMKobS+FfYND vSpXfysTjAh1auhR4sRA1SE8QkfQPsam2Sy9KQ5EKlb4Uh/6w2l0qyxXtmhmHkrdLaLJ t1haYufhoRoK39xzRsKXx2vvojPwODyxwZh3X7QOWcziT1wRzN5cgGBwp8Zc8QECHnLM PH7GEQCi6ELPEK7/RI4iPyUOTv5HWWh3yX3xqGhbL4hIAYUxf+iFYJclRVm8iliMgKZf fYoQ== X-Gm-Message-State: ALoCoQlUOaGVZPE366Ms4vsafgX3Ah1kBZ2nxyOCvELYm/06NdHwqyDkGkRO1fS/R8L1oq/Ynlrn X-Received: by 10.70.64.225 with SMTP id r1mr4099971pds.167.1405621354740; Thu, 17 Jul 2014 11:22:34 -0700 (PDT) Received: from localhost ([2001:5a8:4:83c0:fccf:79b7:dc5b:f307]) by mx.google.com with ESMTPSA id zh7sm1681989pab.1.2014.07.17.11.22.32 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 17 Jul 2014 11:22:33 -0700 (PDT) From: Andy Lutomirski To: kvm@vger.kernel.org, "H. Peter Anvin" , Theodore Ts'o , linux-kernel@vger.kernel.org, Kees Cook , x86@kernel.org Cc: Daniel Borkmann , Srivatsa Vaddagiri , Raghavendra K T , Gleb Natapov , Paolo Bonzini , bsd@redhat.com, Andrew Honig , Andy Lutomirski Subject: [PATCH v4 2/5] random: Add and use arch_get_rng_seed Date: Thu, 17 Jul 2014 11:22:17 -0700 Message-Id: <9c2a0549519b4eb5eee2d5d480f8e83a574273df.1405620944.git.luto@amacapital.net> X-Mailer: git-send-email 1.9.3 In-Reply-To: References: In-Reply-To: References: Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently, init_std_data contains its own logic for using arch random sources. This logic is a bit strange: it reads one long of arch random data per byte of internal state. This replaces that logic with a generic function arch_get_rng_seed that allows arch code to supply its own logic. The default implementation tries arch_get_random_seed_long and arch_get_random_long individually, requesting one bit per bit of internal state being seeded. Assuming the arch sources are perfect, this is the right thing to do. They're not, though, so the followup patch attempts to implement the correct logic on x86. Signed-off-by: Andy Lutomirski --- drivers/char/random.c | 14 +++++++++++--- include/linux/random.h | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 0a7ac0a..be7a94e 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1236,6 +1236,10 @@ void get_random_bytes_arch(void *buf, int nbytes) } EXPORT_SYMBOL(get_random_bytes_arch); +static void seed_entropy_store(void *ctx, u32 data) +{ + mix_pool_bytes((struct entropy_store *)ctx, &data, sizeof(data), NULL); +} /* * init_std_data - initialize pool with system data @@ -1251,15 +1255,19 @@ static void init_std_data(struct entropy_store *r) int i; ktime_t now = ktime_get_real(); unsigned long rv; + char log_prefix[128]; r->last_pulled = jiffies; mix_pool_bytes(r, &now, sizeof(now), NULL); for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) { - if (!arch_get_random_seed_long(&rv) && - !arch_get_random_long(&rv)) - rv = random_get_entropy(); + rv = random_get_entropy(); mix_pool_bytes(r, &rv, sizeof(rv), NULL); } + + sprintf(log_prefix, "random: seeded %s pool", r->name); + arch_get_rng_seed(r, seed_entropy_store, 8 * r->poolinfo->poolbytes, + log_prefix); + mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL); } diff --git a/include/linux/random.h b/include/linux/random.h index 57fbbff..a17065e 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -106,6 +106,46 @@ static inline int arch_has_random_seed(void) } #endif +#ifndef __HAVE_ARCH_GET_RNG_SEED + +/** + * arch_get_rng_seed() - get architectural rng seed data + * @ctx: context for the seed function + * @seed: function to call for each u32 obtained + * @bits_per_source: number of bits from each source to try to use + * @log_prefix: beginning of log output (may be NULL) + * + * Synchronously load some architectural entropy or other best-effort + * random seed data. An arch-specific implementation should be no worse + * than this generic implementation. If the arch code does something + * interesting, it may log something of the form "log_prefix with + * 8 bits of stuff". + * + * No arch-specific implementation should be any worse than the generic + * implementation. + */ +static inline void arch_get_rng_seed(void *ctx, + void (*seed)(void *ctx, u32 data), + int bits_per_source, + const char *log_prefix) +{ + int i, longs = (bits_per_source + BITS_PER_LONG - 1) / BITS_PER_LONG; + + for (i = 0; i < longs; i++) { + unsigned long rv; + + if (arch_get_random_seed_long(&rv) || + arch_get_random_long(&rv)) { + seed(ctx, (u32)rv); +#if BITS_PER_LONG > 32 + seed(ctx, (u32)(rv >> 32)); +#endif + } + } +} + +#endif /* __HAVE_ARCH_GET_RNG_SEED */ + /* Pseudo random number generator from numerical recipes. */ static inline u32 next_pseudo_random32(u32 seed) {