From patchwork Tue Aug 14 17:15:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Junaid Shahid X-Patchwork-Id: 10565905 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 462941390 for ; Tue, 14 Aug 2018 17:15:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 251712A50D for ; Tue, 14 Aug 2018 17:15:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 184382A517; Tue, 14 Aug 2018 17:15:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.5 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, USER_IN_DEF_DKIM_WL autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8A3992A50D for ; Tue, 14 Aug 2018 17:15:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387566AbeHNUDr (ORCPT ); Tue, 14 Aug 2018 16:03:47 -0400 Received: from mail-ua1-f74.google.com ([209.85.222.74]:56383 "EHLO mail-ua1-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387422AbeHNUDr (ORCPT ); Tue, 14 Aug 2018 16:03:47 -0400 Received: by mail-ua1-f74.google.com with SMTP id u26-v6so10374048uan.23 for ; Tue, 14 Aug 2018 10:15:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=GQRMh9K4G987tW6H3/a/j2RcxlKo801PZm83iXm2a2U=; b=uUB91cR6DUiKf4K1fLEr/cEa3df1m4TomX5yWYuUemXbpHTkN+CuXn06lOuDZaik6h mVz7XXW4Mel/BjqnWkjxnQCwfkDIUWOXiE15O6O0Yc5IEWhBiLO59pVAORDXQLtdUxuM 2qbV/Xs9KlrQrJBRjwvstTSlG9Iooqhtkk5Nm9q6ORI9/pycKFbHOtOQlkD6uwAH/RV0 den9vX9ypH+xON3AFX3MNW2i4nJmQGICtQxH8dUr5zFP/mhVrLJUjDxzwTo1if0RMber q6NsobERdyGkkRNJIU2B14TwjNtaDJc2O90/Exi6RCBVURbnlyQWqjQp+mrunAIn231c NDEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=GQRMh9K4G987tW6H3/a/j2RcxlKo801PZm83iXm2a2U=; b=MGQSjID53k1ABtOT6+THWwciq6s6uZ9tZLTb7TgIzSI5Ol7CNAbYJx3Tzq5x+f+PaW de8+35Ro4dPsfe71qVwUc5Rj4UKjp3fmi7WY33jwhkbYrY+vO9ulcJKr2rQjC7lfZ3/1 esnjdCocq3mWlIME4p2UhqI6B9wzJGSQfFEGLjjDSZ9y19Z2PwMZxo1gnZ/sdu5i4UtY xksNrw3ch0evU9U09pX8ZEUMOD+qKxyw4y4ZKXxk0uNY/8kN1Slk7WdBc99eYhlKY3/+ h6HrDOSeHG/xC/WPJNJ8vw2zjjXvoyaPLG68rJjXIpuvEQa2NQxjXMRejrDW2C1dUVMP jjfA== X-Gm-Message-State: AOUpUlE/J1pcaKnHMJSLbOSJGn39DdPIqADnHrAsSHPJp5hV2rXbmlk+ UVffnZep4bgKoy8nKQVXC/K+jF+M3x6w X-Google-Smtp-Source: AA+uWPye4Ctsl6RNyLk8bXr0DLOzm/8lp8eC6OMZND4MVdKVGjKqPmRER1YyfArKpB7zTuBTTqUrhGQ1cQzg X-Received: by 2002:a1f:340c:: with SMTP id b12-v6mr12600136vka.31.1534266943704; Tue, 14 Aug 2018 10:15:43 -0700 (PDT) Date: Tue, 14 Aug 2018 10:15:34 -0700 Message-Id: <20180814171534.61890-1-junaids@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.18.0.345.g5c9ce644c3-goog Subject: [PATCH] kvm: x86: Set highest physical address bits in non-present/reserved SPTEs From: Junaid Shahid To: pbonzini@redhat.com Cc: kvm@vger.kernel.org, andreslc@google.com, jmattson@google.com Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Always set the 5 upper-most supported physical address bits to 1 for SPTEs that are marked as non-present or reserved, to make them unusable for L1TF attacks from the guest. Currently, this just applies to MMIO SPTEs. (We do not need to mark PTEs that are completely 0 as physical page 0 is already reserved.) This allows mitigation of L1TF without disabling hyper-threading by using shadow paging mode instead of EPT. Signed-off-by: Junaid Shahid --- arch/x86/kvm/mmu.c | 43 ++++++++++++++++++++++++++++++++++++++----- arch/x86/kvm/x86.c | 8 ++++++-- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 6b8f11521c41..4cfc5c8b6e61 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -221,6 +221,17 @@ static const u64 shadow_acc_track_saved_bits_mask = PT64_EPT_READABLE_MASK | PT64_EPT_EXECUTABLE_MASK; static const u64 shadow_acc_track_saved_bits_shift = PT64_SECOND_AVAIL_BITS_SHIFT; +/* + * This mask must be set on all non-zero Non-Present or Reserved SPTEs in order + * to guard against L1TF attacks. + */ +static u64 __read_mostly shadow_nonpresent_or_rsvd_mask; + +/* + * The number of high-order 1 bits to use in the mask above. + */ +static const u64 shadow_nonpresent_or_rsvd_mask_len = 5; + static void mmu_spte_set(u64 *sptep, u64 spte); void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask, u64 mmio_value) @@ -308,9 +319,13 @@ static void mark_mmio_spte(struct kvm_vcpu *vcpu, u64 *sptep, u64 gfn, { unsigned int gen = kvm_current_mmio_generation(vcpu); u64 mask = generation_mmio_spte_mask(gen); + u64 gpa = gfn << PAGE_SHIFT; access &= ACC_WRITE_MASK | ACC_USER_MASK; - mask |= shadow_mmio_value | access | gfn << PAGE_SHIFT; + mask |= shadow_mmio_value | shadow_nonpresent_or_rsvd_mask; + mask |= access | gpa; + mask |= (gpa & shadow_nonpresent_or_rsvd_mask) + << shadow_nonpresent_or_rsvd_mask_len; trace_mark_mmio_spte(sptep, gfn, access, gen); mmu_spte_set(sptep, mask); @@ -323,8 +338,14 @@ static bool is_mmio_spte(u64 spte) static gfn_t get_mmio_spte_gfn(u64 spte) { - u64 mask = generation_mmio_spte_mask(MMIO_GEN_MASK) | shadow_mmio_mask; - return (spte & ~mask) >> PAGE_SHIFT; + u64 mask = generation_mmio_spte_mask(MMIO_GEN_MASK) | shadow_mmio_mask | + shadow_nonpresent_or_rsvd_mask; + u64 gpa = spte & ~mask; + + gpa |= (spte >> shadow_nonpresent_or_rsvd_mask_len) + & shadow_nonpresent_or_rsvd_mask; + + return gpa >> PAGE_SHIFT; } static unsigned get_mmio_spte_access(u64 spte) @@ -381,7 +402,7 @@ void kvm_mmu_set_mask_ptes(u64 user_mask, u64 accessed_mask, } EXPORT_SYMBOL_GPL(kvm_mmu_set_mask_ptes); -static void kvm_mmu_clear_all_pte_masks(void) +static void kvm_mmu_reset_all_pte_masks(void) { shadow_user_mask = 0; shadow_accessed_mask = 0; @@ -391,6 +412,18 @@ static void kvm_mmu_clear_all_pte_masks(void) shadow_mmio_mask = 0; shadow_present_mask = 0; shadow_acc_track_mask = 0; + + /* + * If the CPU has 46 or less physical address bits, then set an + * appropriate mask to guard against L1TF attacks. Otherwise, it is + * assumed that the CPU is not vulnerable to L1TF. + */ + if (boot_cpu_data.x86_phys_bits < + 52 - shadow_nonpresent_or_rsvd_mask_len) + shadow_nonpresent_or_rsvd_mask = + rsvd_bits(boot_cpu_data.x86_phys_bits - + shadow_nonpresent_or_rsvd_mask_len, + boot_cpu_data.x86_phys_bits - 1); } static int is_cpuid_PSE36(void) @@ -5499,7 +5532,7 @@ int kvm_mmu_module_init(void) { int ret = -ENOMEM; - kvm_mmu_clear_all_pte_masks(); + kvm_mmu_reset_all_pte_masks(); pte_list_desc_cache = kmem_cache_create("pte_list_desc", sizeof(struct pte_list_desc), diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 2b812b3c5088..6cd9d62a2dd3 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -6473,8 +6473,12 @@ static void kvm_set_mmio_spte_mask(void) * Set the reserved bits and the present bit of an paging-structure * entry to generate page fault with PFER.RSV = 1. */ - /* Mask the reserved physical address bits. */ - mask = rsvd_bits(maxphyaddr, 51); + + /* + * Mask the uppermost physical address bit, which would be reserved as + * long as the supported physical address width is less than 52. + */ + mask = 1ull << 51; /* Set the present bit. */ mask |= 1ull;