From eac8ee2c49f9e2c2dfb5b4dbcd23c31e6b14349b Mon Sep 17 00:00:00 2001 From: Martin Radev Date: Thu, 4 Jun 2020 14:57:22 +0200 Subject: [PATCH] x86/sev-es: Make RDRAND a required feature This patch offers a hardening to prevent the HV from 'disabling' KASLR for the VM. With this patch any intercepted cpuid would fail if RDRAND is not offered and already cause a fault in the Linux boot stage. Without RDRAND, KASLR and the initial sequence of kernel stack canaries rely on the TSC for randomness. The HV is able to specify a fixed TSC value by either intercepting RDTSC or specifying a zero multiplier with the TSC_RATIO MSR. Adding such a requirement should not cause any harm for when SEV-ES or SEV-SNP are enabled because in such cases RDRAND should also be supported. Signed-off-by: Martin Radev --- arch/x86/kernel/sev-es-shared.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/sev-es-shared.c b/arch/x86/kernel/sev-es-shared.c index fc6a41ba7fb23a..937ae44b31612b 100644 --- a/arch/x86/kernel/sev-es-shared.c +++ b/arch/x86/kernel/sev-es-shared.c @@ -457,9 +457,12 @@ static enum es_result vc_handle_cpuid(struct ghcb *ghcb, struct pt_regs *regs = ctxt->regs; u32 cr4 = native_read_cr4(); enum es_result ret; + const u32 eax = regs->ax & 0xffffffffU; + const u32 ecx = regs->cx & 0xffffffffU; + const bool request_feature_bits = (eax == 0x1U); - ghcb_set_rax(ghcb, regs->ax & 0xffffffff); - ghcb_set_rcx(ghcb, regs->cx & 0xffffffff); + ghcb_set_rax(ghcb, eax); + ghcb_set_rcx(ghcb, ecx); if (cr4 & X86_CR4_OSXSAVE) /* Safe to read xcr0 */ @@ -478,6 +481,16 @@ static enum es_result vc_handle_cpuid(struct ghcb *ghcb, ghcb_is_valid_rdx(ghcb))) return ES_VMM_ERROR; + /* + * Without RDRAND, KASLR relies on the TSC value for randomnization + * which is controlled by the HV either through interception or modifying + * the TSC_RATIO_MSR. + * As a hardening, RDRAND is made a minimal required feature and VM + * returns error if the HV states that RDRAND is not supported. + */ + if (request_feature_bits && !(ghcb->save.rcx & (1U << 30))) + return ES_VMM_ERROR; + regs->ax = ghcb->save.rax & 0xffffffff; regs->bx = ghcb->save.rbx & 0xffffffff; regs->cx = ghcb->save.rcx & 0xffffffff;