lkml.org 
[lkml]   [2014]   [Aug]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v6 6/7] x86,random,kvm: Use KVM_GET_RNG_SEED in arch_get_rng_seed
Date
This is a straightforward implementation: for each bit of internal
RNG state, request one bit from KVM_GET_RNG_SEED. This is done even
if RDSEED/RDRAND worked, since KVM_GET_RNG_SEED is likely to provide
cryptographically secure output even if the CPU's RNG is weak or
compromised.

Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---
arch/x86/Kconfig | 4 ++++
arch/x86/include/asm/kvm_guest.h | 9 +++++++++
arch/x86/kernel/archrandom.c | 25 ++++++++++++++++++++++++-
arch/x86/kernel/kvm.c | 10 ++++++++++
4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index d24887b..ad87278 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -594,6 +594,7 @@ config KVM_GUEST
bool "KVM Guest support (including kvmclock)"
depends on PARAVIRT
select PARAVIRT_CLOCK
+ select ARCH_RANDOM
default y
---help---
This option enables various optimizations for running under the KVM
@@ -1508,6 +1509,9 @@ config ARCH_RANDOM
If supported, this is a high bandwidth, cryptographically
secure hardware random number generator.

+ This also enables paravirt RNGs such as KVM's if the relevant
+ PV guest support is enabled.
+
config X86_SMAP
def_bool y
prompt "Supervisor Mode Access Prevention" if EXPERT
diff --git a/arch/x86/include/asm/kvm_guest.h b/arch/x86/include/asm/kvm_guest.h
index a92b176..8c4dbd5 100644
--- a/arch/x86/include/asm/kvm_guest.h
+++ b/arch/x86/include/asm/kvm_guest.h
@@ -3,4 +3,13 @@

int kvm_setup_vsyscall_timeinfo(void);

+#if defined(CONFIG_KVM_GUEST) && defined(CONFIG_ARCH_RANDOM)
+extern bool kvm_get_rng_seed(u64 *rv);
+#else
+static inline bool kvm_get_rng_seed(u64 *rv)
+{
+ return false;
+}
+#endif
+
#endif /* _ASM_X86_KVM_GUEST_H */
diff --git a/arch/x86/kernel/archrandom.c b/arch/x86/kernel/archrandom.c
index e8d2ffb..adbaa25 100644
--- a/arch/x86/kernel/archrandom.c
+++ b/arch/x86/kernel/archrandom.c
@@ -15,6 +15,7 @@
*/

#include <asm/archrandom.h>
+#include <asm/kvm_guest.h>

void arch_rng_init(void *ctx,
void (*seed)(void *ctx, u32 data),
@@ -22,7 +23,7 @@ void arch_rng_init(void *ctx,
const char *log_prefix)
{
int i;
- int rdseed_bits = 0, rdrand_bits = 0;
+ int rdseed_bits = 0, rdrand_bits = 0, kvm_bits = 0;
char buf[128] = "";
char *msgptr = buf;

@@ -42,10 +43,32 @@ void arch_rng_init(void *ctx,
#endif
}

+ /*
+ * Use KVM_GET_RNG_SEED regardless of whether the CPU RNG
+ * worked, since it incorporates entropy unavailable to the CPU,
+ * and we shouldn't trust the hardware RNG more than we need to.
+ * We request enough bits for the entire internal RNG state,
+ * because there's no good reason not to.
+ */
+ for (i = 0; i < bits_per_source; i += 64) {
+ u64 rv;
+
+ if (kvm_get_rng_seed(&rv)) {
+ seed(ctx, (u32)rv);
+ seed(ctx, (u32)(rv >> 32));
+ kvm_bits += 8 * sizeof(rv);
+ } else {
+ break; /* If it fails once, it will keep failing. */
+ }
+ }
+
if (rdseed_bits)
msgptr += sprintf(msgptr, ", %d bits from RDSEED", rdseed_bits);
if (rdrand_bits)
msgptr += sprintf(msgptr, ", %d bits from RDRAND", rdrand_bits);
+ if (kvm_bits)
+ msgptr += sprintf(msgptr, ", %d bits from KVM_GET_RNG_BITS",
+ kvm_bits);
if (buf[0])
pr_info("%s with %s\n", log_prefix, buf + 2);
}
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 3dd8e2c..bd8783a 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -416,6 +416,16 @@ void kvm_disable_steal_time(void)
wrmsr(MSR_KVM_STEAL_TIME, 0, 0);
}

+bool kvm_get_rng_seed(u64 *v)
+{
+ /*
+ * Allow migration from a hypervisor with the GET_RNG_SEED
+ * feature to a hypervisor without it.
+ */
+ return (kvm_para_has_feature(KVM_FEATURE_GET_RNG_SEED) &&
+ rdmsrl_safe(MSR_KVM_GET_RNG_SEED, v) == 0);
+}
+
#ifdef CONFIG_SMP
static void __init kvm_smp_prepare_boot_cpu(void)
{
--
1.9.3


\
 
 \ /
  Last update: 2014-08-14 08:01    [W:0.036 / U:0.568 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site