mirror of
https://github.com/torvalds/linux.git
synced 2024-12-04 01:51:34 +00:00
049f9ae93d
The decision of whether or not to trust RDRAND is controlled by the "random.trust_cpu" boot time parameter or the CONFIG_RANDOM_TRUST_CPU compile time default. The "nordrand" flag was added during the early days of RDRAND, when there were worries that merely using its values could compromise the RNG. However, these days, RDRAND values are not used directly but always go through the RNG's hash function, making "nordrand" no longer useful. Rather, the correct switch is "random.trust_cpu", which not only handles the relevant trust issue directly, but also is general to multiple CPU types, not just x86. However, x86 RDRAND does have a history of being occasionally problematic. Prior, when the kernel would notice something strange, it'd warn in dmesg and suggest enabling "nordrand". We can improve on that by making the test a little bit better and then taking the step of automatically disabling RDRAND if we detect it's problematic. Also disable RDSEED if the RDRAND test fails. Cc: x86@kernel.org Cc: Theodore Ts'o <tytso@mit.edu> Suggested-by: H. Peter Anvin <hpa@zytor.com> Suggested-by: Borislav Petkov <bp@suse.de> Acked-by: Borislav Petkov <bp@suse.de> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
50 lines
1.2 KiB
C
50 lines
1.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* This file is part of the Linux kernel.
|
|
*
|
|
* Copyright (c) 2011, Intel Corporation
|
|
* Authors: Fenghua Yu <fenghua.yu@intel.com>,
|
|
* H. Peter Anvin <hpa@linux.intel.com>
|
|
*/
|
|
|
|
#include <asm/processor.h>
|
|
#include <asm/archrandom.h>
|
|
#include <asm/sections.h>
|
|
|
|
/*
|
|
* RDRAND has Built-In-Self-Test (BIST) that runs on every invocation.
|
|
* Run the instruction a few times as a sanity check. Also make sure
|
|
* it's not outputting the same value over and over, which has happened
|
|
* as a result of past CPU bugs.
|
|
*
|
|
* If it fails, it is simple to disable RDRAND and RDSEED here.
|
|
*/
|
|
|
|
void x86_init_rdrand(struct cpuinfo_x86 *c)
|
|
{
|
|
enum { SAMPLES = 8, MIN_CHANGE = 5 };
|
|
unsigned long sample, prev;
|
|
bool failure = false;
|
|
size_t i, changed;
|
|
|
|
if (!cpu_has(c, X86_FEATURE_RDRAND))
|
|
return;
|
|
|
|
for (changed = 0, i = 0; i < SAMPLES; ++i) {
|
|
if (!rdrand_long(&sample)) {
|
|
failure = true;
|
|
break;
|
|
}
|
|
changed += i && sample != prev;
|
|
prev = sample;
|
|
}
|
|
if (changed < MIN_CHANGE)
|
|
failure = true;
|
|
|
|
if (failure) {
|
|
clear_cpu_cap(c, X86_FEATURE_RDRAND);
|
|
clear_cpu_cap(c, X86_FEATURE_RDSEED);
|
|
pr_emerg("RDRAND is not reliable on this platform; disabling.\n");
|
|
}
|
|
}
|