Received: by 2002:a05:6a10:6744:0:0:0:0 with SMTP id w4csp3699894pxu; Mon, 19 Oct 2020 20:21:54 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx3o6ZyscM7Ww3H/qR0R9twiihbvA1TAtgrixLAGufSQPY2NvGeWgycf5JB0jP1iviDFb5T X-Received: by 2002:a17:906:3fd3:: with SMTP id k19mr1102674ejj.434.1603164113867; Mon, 19 Oct 2020 20:21:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1603164113; cv=none; d=google.com; s=arc-20160816; b=Ilcv9vl1lAJ2dJymj3xt+myouR/N1I/IqmFMf3630oRqVtXVyxGBFut+kSOZOY2sDw lp2ENHZQ67QXNBusQq4LTwkYJZfsQGLJlTdKrya0xzMpavgJlt/LG3xInEmtAdDgrcfQ tjH7N5eKvMZdcFRYcPPG6DgE2JOhoBNBp0aTW+Tx9oVtK68xD/RVjdR7HIeVHEsjySq/ AgonTzmn6PUUpF0zhLzO5K6G4ivXzVnB9vZAE1DDwrFTJZRYWauIdfI45u7tnmYzI43h DORv63el+HLzYd1j8wMc5e3FXFgRZEAUwtRTwD1wwvlcr0Yi5x+E5sCPYWnvXCV76GJ9 aEKA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=pO6qAZtjk8RWipSVJa9HWK6tibY+j0S0bXYyIChm7Zk=; b=mE2Sg6f8O7icmblrbwSB0pwbBUTo0h0WqEq3E+PVVZrMRh0cm7h4Mp+rIKQn9j+GxK hiEBxeXiaJ98S80agESF9Amlp22hX3EUwLPffUUjU/Su2h33fbiIlvY+1t7rnmeoxsw4 9go894ktTT9cUHyPZy1St2LkMkICDaq9bdLpda9Rw6MJt/EyDnq1O6HN9XVeEWkvwxmg j4VRn0Z9QpvAZdYDlmO/jZMKlHtUo3OmZpMqJRYVpzeZ1Kkno7QB54zi9mQ4chNanv1f 7EoMOo5cG38xg5xQwA/oyx800Rfs/l850RMEQIUmWXuM4oDPD49UwrpX9PP+goj2lVYf R89A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=8bytes.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id y16si404277edq.337.2020.10.19.20.21.32; Mon, 19 Oct 2020 20:21:53 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=8bytes.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729962AbgJSPL3 (ORCPT + 99 others); Mon, 19 Oct 2020 11:11:29 -0400 Received: from 8bytes.org ([81.169.241.247]:33492 "EHLO theia.8bytes.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729776AbgJSPL0 (ORCPT ); Mon, 19 Oct 2020 11:11:26 -0400 Received: from cap.home.8bytes.org (p549add56.dip0.t-ipconnect.de [84.154.221.86]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by theia.8bytes.org (Postfix) with ESMTPSA id 44C324C3; Mon, 19 Oct 2020 17:11:24 +0200 (CEST) From: Joerg Roedel To: x86@kernel.org Cc: Joerg Roedel , Joerg Roedel , Thomas Gleixner , Ingo Molnar , Borislav Petkov , "H. Peter Anvin" , Dave Hansen , Andy Lutomirski , Peter Zijlstra , Kees Cook , Arvind Sankar , Martin Radev , Tom Lendacky , linux-kernel@vger.kernel.org Subject: [PATCH 3/5] x86/boot/compressed/64: Check SEV encryption in 64-bit boot-path Date: Mon, 19 Oct 2020 17:11:19 +0200 Message-Id: <20201019151121.826-4-joro@8bytes.org> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201019151121.826-1-joro@8bytes.org> References: <20201019151121.826-1-joro@8bytes.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Joerg Roedel Check whether the hypervisor reported the correct C-bit when running as an SEV guest. Using a wrong C-bit position could be used to leak sensitive data from the guest to the hypervisor. The check function is in arch/x86/kernel/sev_verify_cbit.S so that it can be re-used in the running kernel image. Signed-off-by: Joerg Roedel --- arch/x86/boot/compressed/ident_map_64.c | 1 + arch/x86/boot/compressed/mem_encrypt.S | 4 ++ arch/x86/boot/compressed/misc.h | 2 + arch/x86/kernel/sev_verify_cbit.S | 77 +++++++++++++++++++++++++ 4 files changed, 84 insertions(+) create mode 100644 arch/x86/kernel/sev_verify_cbit.S diff --git a/arch/x86/boot/compressed/ident_map_64.c b/arch/x86/boot/compressed/ident_map_64.c index 063a60edcf99..73abba3312a7 100644 --- a/arch/x86/boot/compressed/ident_map_64.c +++ b/arch/x86/boot/compressed/ident_map_64.c @@ -153,6 +153,7 @@ void initialize_identity_maps(void) * into cr3. */ add_identity_map((unsigned long)_head, (unsigned long)_end); + sev_verify_cbit(top_level_pgt); write_cr3(top_level_pgt); } diff --git a/arch/x86/boot/compressed/mem_encrypt.S b/arch/x86/boot/compressed/mem_encrypt.S index 0effd58f0095..1786d5f02825 100644 --- a/arch/x86/boot/compressed/mem_encrypt.S +++ b/arch/x86/boot/compressed/mem_encrypt.S @@ -68,6 +68,9 @@ SYM_FUNC_START(get_sev_encryption_bit) SYM_FUNC_END(get_sev_encryption_bit) .code64 + +#include "../../kernel/sev_verify_cbit.S" + SYM_FUNC_START(set_sev_encryption_mask) #ifdef CONFIG_AMD_MEM_ENCRYPT push %rbp @@ -109,4 +112,5 @@ SYM_FUNC_END(set_sev_encryption_mask) .balign 8 SYM_DATA(sme_me_mask, .quad 0) SYM_DATA(sev_status, .quad 0) +SYM_DATA(sev_check_data, .quad 0) #endif diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h index 6d31f1b4c4d1..53f4848ad392 100644 --- a/arch/x86/boot/compressed/misc.h +++ b/arch/x86/boot/compressed/misc.h @@ -159,4 +159,6 @@ void boot_page_fault(void); void boot_stage1_vc(void); void boot_stage2_vc(void); +void sev_verify_cbit(unsigned long cr3); + #endif /* BOOT_COMPRESSED_MISC_H */ diff --git a/arch/x86/kernel/sev_verify_cbit.S b/arch/x86/kernel/sev_verify_cbit.S new file mode 100644 index 000000000000..5b6f61465437 --- /dev/null +++ b/arch/x86/kernel/sev_verify_cbit.S @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * sev_verify_cbit.S - Code for verification of the C-bit position reported + * by the Hypervisor when running with SEV enabled. + * + * Copyright (c) 2020 Joerg Roedel (jroedel@suse.de) + * + * Implements sev_verify_cbit() which is called before switching to a new + * long-mode page-table at boot. + * + * It verifies that the C-bit position is correct by writing a random value to + * an encrypted memory location while on the current page-table. Then it + * switches to the new page-table to verify the memory content is still the + * same. After that it switches back to the current page-table and when the + * check succeeded it returns. If the check failed the code invalidates the + * stack pointer and goes into a hlt loop. The stack-pointer is invalidated to + * make sure no interrupt or exception can get the CPU out of the hlt loop. + * + * New page-table pointer is expected in %rdi (first parameter) + * + */ +SYM_FUNC_START(sev_verify_cbit) +#ifdef CONFIG_AMD_MEM_ENCRYPT + /* First check if a C-bit was detected */ + movq sme_me_mask(%rip), %r10 + testq %r10, %r10 + jz 3f + + /* sme_me_mask != 0 could mean SME or SEV - Check also for SEV */ + movq sev_status(%rip), %r10 + testq %r10, %r10 + jz 3f + + /* + * Verified that running under SEV - now get a random value using + * RDRAND. This instruction is mandatory when running as an SEV guest. + * + * Don't bail out of the loop if RDRAND returns errors. It is better to + * prevent forward progress than to work with a non-random value here. + */ +1: rdrand %r10 + jnc 1b + + /* Store value to memory and keep it in %r10 */ + movq %r10, sev_check_data(%rip) + + /* Backup current %cr3 value to restore it later */ + movq %cr3, %r11 + + /* Switch to new %cr3 - This might unmap the stack */ + movq %rdi, %cr3 + + /* + * Compare value in %r10 with memory location - If C-Bit is incorrect + * this would read the encrypted data and make the check fail. + */ + cmpq %r10, sev_check_data(%rip) + + /* Restore old %cr3 */ + movq %r11, %cr3 + + /* Check CMPQ result */ + je 3f + + /* + * The check failed - Prevent any forward progress to prevent ROP + * attacks, invalidate the stack and go into a hlt loop. + */ + xorq %rsp, %rsp + subq $0x1000, %rsp +2: hlt + jmp 2b +3: +#endif + ret +SYM_FUNC_END(sev_verify_cbit) + -- 2.28.0