From nobody Tue Apr 28 22:07:26 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 37CF9C433F5 for ; Fri, 27 May 2022 17:07:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1354187AbiE0RHL (ORCPT ); Fri, 27 May 2022 13:07:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34420 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353963AbiE0RHE (ORCPT ); Fri, 27 May 2022 13:07:04 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 44EEA6D4EB for ; Fri, 27 May 2022 10:07:03 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id z186-20020a6233c3000000b00510a6bc2864so2722316pfz.10 for ; Fri, 27 May 2022 10:07:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=XII5Q10d7IHsakcWieNQERcqnrzaW3r3Psj82Eh20aM=; b=aoLBo78gEFsnTeaEtyl/yOVL8Nlif46gSYrgLxN+AxYSm6eLmAHzRamQ52sLcjj4gP 7+Busc3BGlBQjxG2BxGhT/bt5YyxaX25hVC1F1PEe37LR/wTZllnnlkaU8ET66WXGciz t+UfNNWyiZGvQawZCzNfpaNeInXdzdZS96Uu5FjDPGgJrlmS9q+z8leELQzFhyLY2aES OPVe4QU6oaq1wXBKgI5+ckIW9pP5BAoIPJ0EdUztR9MYwUXAjyzGtKlgu+P2S/iLBPPn VcrHzkcyLm4wLyH3598hDlUDcU4pOUqnYwkDSQRt0SAiDA5RuFyceNt9Bp8v0M5B8gFl be8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=XII5Q10d7IHsakcWieNQERcqnrzaW3r3Psj82Eh20aM=; b=oOpEEqTYUpXNP0U7YokYMt/WG4rYrrd6YupwxJzuM1Z9IvGwz3tiotBHVTOAdBdeNe He7aRrnb5KUpeU5hxeLJfCVv0JLy9BpbeRFA71gFZ/S3ocja7r8QquSFWhrWaLbj8UNx 0Ze8kLKwEHGqV50Dn1qnUhxfgSeKSFJytLqewjs8ERTXkVdWnNwhpaLQOQHEPxNPQzQo MgllteUMB9lj+Q6NMxSevUOAl1RnktVb6CeT9j4Dj9z025usje0+JfM1I4cRKPpv7I8u P1Ts8fe/y3eYqABXZTfUy3Lpu5Xtre2Ysl00WE3T/JHQpwoaOUOvX2ZB5qtrQyC4yQ+b 4hJQ== X-Gm-Message-State: AOAM533uGXeAJf5AbdUdNQjwK6/Y6VLdafiQDoJbV7Hypve8FbQ9o6R4 Ovp37fKRROfWWvyAUFi2ANZAQ6UmMw0= X-Google-Smtp-Source: ABdhPJxqoqZZBsn67a+/tmIpuPg4SlJS7NvBnjiLn5lus3F6VCY441LbmBbN2C6gA0x5Q95LyQVEGob22Nw= X-Received: from seanjc.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3e5]) (user=seanjc job=sendgmr) by 2002:a17:902:8608:b0:158:c532:d8b2 with SMTP id f8-20020a170902860800b00158c532d8b2mr43964184plo.46.1653671222592; Fri, 27 May 2022 10:07:02 -0700 (PDT) Reply-To: Sean Christopherson Date: Fri, 27 May 2022 17:06:57 +0000 In-Reply-To: <20220527170658.3571367-1-seanjc@google.com> Message-Id: <20220527170658.3571367-2-seanjc@google.com> Mime-Version: 1.0 References: <20220527170658.3571367-1-seanjc@google.com> X-Mailer: git-send-email 2.36.1.255.ge46751e96f-goog Subject: [PATCH v2 1/2] KVM: VMX: Sanitize VM-Entry/VM-Exit control pairs at kvm_intel load time From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Chenyi Qiang , Lei Wang Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Sanitize the VM-Entry/VM-Exit control pairs (load+load or load+clear) during setup instead of checking both controls in a pair at runtime. If only one control is supported, KVM will report the associated feature as not available, but will leave the supported control bit set in the VMCS config, which could lead to corruption of host state. E.g. if only the VM-Entry control is supported and the feature is not dynamically toggled, KVM will set the control in all VMCSes and load zeros without restoring host state. Note, while this is technically a bug fix, practically speaking no sane CPU or VMM would support only one control. KVM's behavior of checking both controls is mostly pedantry. Cc: Chenyi Qiang Cc: Lei Wang Signed-off-by: Sean Christopherson --- arch/x86/kvm/vmx/capabilities.h | 13 ++++--------- arch/x86/kvm/vmx/vmx.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilitie= s.h index dc2cb8a16e76..464bf39e4835 100644 --- a/arch/x86/kvm/vmx/capabilities.h +++ b/arch/x86/kvm/vmx/capabilities.h @@ -97,20 +97,17 @@ static inline bool cpu_has_vmx_posted_intr(void) =20 static inline bool cpu_has_load_ia32_efer(void) { - return (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_EFER) && - (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_EFER); + return vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_EFER; } =20 static inline bool cpu_has_load_perf_global_ctrl(void) { - return (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL) && - (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL); + return vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL; } =20 static inline bool cpu_has_vmx_mpx(void) { - return (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_BNDCFGS) && - (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_BNDCFGS); + return vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_BNDCFGS; } =20 static inline bool cpu_has_vmx_tpr_shadow(void) @@ -377,7 +374,6 @@ static inline bool cpu_has_vmx_intel_pt(void) rdmsrl(MSR_IA32_VMX_MISC, vmx_msr); return (vmx_msr & MSR_IA32_VMX_MISC_INTEL_PT) && (vmcs_config.cpu_based_2nd_exec_ctrl & SECONDARY_EXEC_PT_USE_GPA) && - (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_IA32_RTIT_CTL) && (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_RTIT_CTL); } =20 @@ -406,8 +402,7 @@ static inline bool vmx_pebs_supported(void) =20 static inline bool cpu_has_vmx_arch_lbr(void) { - return (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_IA32_LBR_CTL) && - (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_LBR_CTL); + return vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_LBR_CTL; } =20 static inline u64 vmx_get_perf_capabilities(void) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 6927f6e8ec31..a592b424fbbc 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -2473,6 +2473,24 @@ static __init int setup_vmcs_config(struct vmcs_conf= ig *vmcs_conf, u64 _cpu_based_3rd_exec_control =3D 0; u32 _vmexit_control =3D 0; u32 _vmentry_control =3D 0; + int i; + + /* + * LOAD/SAVE_DEBUG_CONTROLS are absent because both are mandatory. + * SAVE_IA32_PAT and SAVE_IA32_EFER are absent because KVM always + * intercepts writes to PAT and EFER, i.e. never enables those controls. + */ + struct { + u32 entry_control; + u32 exit_control; + } const vmcs_entry_exit_pairs[] =3D { + { VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL, VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTR= L }, + { VM_ENTRY_LOAD_IA32_PAT, VM_EXIT_LOAD_IA32_PAT }, + { VM_ENTRY_LOAD_IA32_EFER, VM_EXIT_LOAD_IA32_EFER }, + { VM_ENTRY_LOAD_BNDCFGS, VM_EXIT_CLEAR_BNDCFGS }, + { VM_ENTRY_LOAD_IA32_RTIT_CTL, VM_EXIT_CLEAR_IA32_RTIT_CTL }, + { VM_ENTRY_LOAD_IA32_LBR_CTL, VM_EXIT_CLEAR_IA32_LBR_CTL }, + }; =20 memset(vmcs_conf, 0, sizeof(*vmcs_conf)); min =3D CPU_BASED_HLT_EXITING | @@ -2614,6 +2632,20 @@ static __init int setup_vmcs_config(struct vmcs_conf= ig *vmcs_conf, &_vmentry_control) < 0) return -EIO; =20 + for (i =3D 0; i < ARRAY_SIZE(vmcs_entry_exit_pairs); i++) { + u32 n_ctrl =3D vmcs_entry_exit_pairs[i].entry_control; + u32 x_ctrl =3D vmcs_entry_exit_pairs[i].exit_control; + + if (!(_vmentry_control & n_ctrl) =3D=3D !(_vmexit_control & x_ctrl)) + continue; + + pr_warn_once("Inconsistent VM-Entry/VM-Exit pair, entry =3D %x, exit =3D= %x\n", + _vmentry_control & n_ctrl, _vmexit_control & x_ctrl); + + _vmentry_control &=3D ~n_ctrl; + _vmexit_control &=3D ~x_ctrl; + } + /* * Some cpus support VM_{ENTRY,EXIT}_IA32_PERF_GLOBAL_CTRL but they * can't be used due to an errata where VM Exit may incorrectly clear --=20 2.36.1.255.ge46751e96f-goog From nobody Tue Apr 28 22:07:26 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0F7B4C433EF for ; Fri, 27 May 2022 17:07:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1349258AbiE0RHO (ORCPT ); Fri, 27 May 2022 13:07:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34534 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1354165AbiE0RHG (ORCPT ); Fri, 27 May 2022 13:07:06 -0400 Received: from mail-pf1-x449.google.com (mail-pf1-x449.google.com [IPv6:2607:f8b0:4864:20::449]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 062A376289 for ; Fri, 27 May 2022 10:07:05 -0700 (PDT) Received: by mail-pf1-x449.google.com with SMTP id c12-20020aa7880c000000b00518c9705941so2710469pfo.20 for ; Fri, 27 May 2022 10:07:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=/UYpE3ORfUWUOgObAVh8AEEShSSgV4nNzE6TIkUvoL4=; b=TQeHEjgzosI03XNozW4xpCMZ9JxfuOpyVuGRddKE0ma/DiCtuvES/HGw8OCoLGaaVm FXr+UDQOUghyc8ovjUi+J/5fUG4E0TqoRGE/9BDUmv18uG0XVW6ciqTSD7yuQGrJ1i0l BquCrdDen83aMQ+FJvy9BKijtWgUXWD2EPsSFLBIfBYPEqrmYwQ1FaIfGNp7j/5x+UyJ +hjb1NRq/OEPbEbdJUuE51nrckFUuH40hY48qbAzp2dXxzwk7KyEdrjQW5GYVvfz40Lu GcR4kFxEv3iQeJqee+8IPGGcOJOBgs4XH6rP8EmOJ9H/JnrNZwpRuQSyVG5y0Mpqmhrj ks0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=/UYpE3ORfUWUOgObAVh8AEEShSSgV4nNzE6TIkUvoL4=; b=vxLg5N7O9pkuGQj4YUC6aTLKjwez3kctbsall4BqPjyPAwtWHMwLqVD04+ycRd7WiO U96pjx0HPtPhBYc1cBvUpHS2iYDv9wan4DwSPpfgap79YNMPHUMwJwHquD9fM305jTXR TBfRoQeOPA0wt2Ri5Fh7KyVrm0VaI/zzeKs4g6nuYODr97oXqwE0NO+7xf9kjyxiPfCe lIrkQTL3N1q5WNY+nyl24HjmtOJBuH8PomkVn8fgua+sDXjCaBT+XkmOunBOL1UPeueo qwpbzSFjnvrnSlQ49nCOp3GatRcXM0rHficOrZXlbjt3S/UI64zRBavxoj/I3bsSchad aMTw== X-Gm-Message-State: AOAM533UKhR2WkHd6PYf8K/swjwVWwWBZkfyY9IdQN8J3pHU8SUJ3dVP NZvNxfO+zMqwGHH9VqLHNhgvKuoYbXc= X-Google-Smtp-Source: ABdhPJzKD8foVyPbZhCsSXtLbePPpsaS3Oi+ipHHra/WbFzZbW5aDHKJGWu55k2n9gGuWs4O+81BestqKnA= X-Received: from seanjc.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:3e5]) (user=seanjc job=sendgmr) by 2002:a17:902:bb90:b0:158:a031:2ff2 with SMTP id m16-20020a170902bb9000b00158a0312ff2mr43681179pls.117.1653671224527; Fri, 27 May 2022 10:07:04 -0700 (PDT) Reply-To: Sean Christopherson Date: Fri, 27 May 2022 17:06:58 +0000 In-Reply-To: <20220527170658.3571367-1-seanjc@google.com> Message-Id: <20220527170658.3571367-3-seanjc@google.com> Mime-Version: 1.0 References: <20220527170658.3571367-1-seanjc@google.com> X-Mailer: git-send-email 2.36.1.255.ge46751e96f-goog Subject: [PATCH v2 2/2] KVM: VMX: Reject kvm_intel if an inconsistent VMCS config is detected From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Chenyi Qiang , Lei Wang Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add an on-by-default module param, error_on_inconsistent_vmcs_config, to allow rejecting the load of kvm_intel if an inconsistent VMCS config is detected. Continuing on with an inconsistent, degraded config is undesirable in the vast majority of use cases, e.g. may result in a misconfigured VM, poor performance due to lack of fast MSR switching, or even security issues in the unlikely event the guest is relying on MPX. Practically speaking, an inconsistent VMCS config should never be encountered in a production quality environment, e.g. on bare metal it indicates a silicon defect (or a disturbing lack of validation by the hardware vendor), and in a virtualized machine (KVM as L1) it indicates a buggy/misconfigured L0 VMM/hypervisor. Provide a module param to override the behavior for testing purposes, or in the unlikely scenario that KVM is deployed on a flawed-but-usable CPU or virtual machine. Note, what is or isn't an inconsistency is somewhat subjective, e.g. one might argue that LOAD_EFER without SAVE_EFER is an inconsistency. KVM's unofficial guideline for an "inconsistency" is either scenarios that are completely nonsensical, e.g. the existing checks on having EPT/VPID knobs without EPT/VPID, and/or scenarios that prevent KVM from virtualizing or utilizing a feature, e.g. the unpaired entry/exit controls checks. Other checks that fall into one or both of the covered scenarios could be added in the future, e.g. asserting that a VMCS control exists available if and only if the associated feature is supported in bare metal. Signed-off-by: Sean Christopherson --- arch/x86/kvm/vmx/vmx.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index a592b424fbbc..74202512f861 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -119,6 +119,9 @@ module_param(nested, bool, S_IRUGO); bool __read_mostly enable_pml =3D 1; module_param_named(pml, enable_pml, bool, S_IRUGO); =20 +static bool __read_mostly error_on_inconsistent_vmcs_config =3D true; +module_param(error_on_inconsistent_vmcs_config, bool, 0444); + static bool __read_mostly dump_invalid_vmcs =3D 0; module_param(dump_invalid_vmcs, bool, 0644); =20 @@ -2574,15 +2577,23 @@ static __init int setup_vmcs_config(struct vmcs_con= fig *vmcs_conf, CPU_BASED_CR3_STORE_EXITING | CPU_BASED_INVLPG_EXITING); } else if (vmx_cap->ept) { - vmx_cap->ept =3D 0; pr_warn_once("EPT CAP should not exist if not support " "1-setting enable EPT VM-execution control\n"); + + if (error_on_inconsistent_vmcs_config) + return -EIO; + + vmx_cap->ept =3D 0; } if (!(_cpu_based_2nd_exec_control & SECONDARY_EXEC_ENABLE_VPID) && - vmx_cap->vpid) { - vmx_cap->vpid =3D 0; + vmx_cap->vpid) { pr_warn_once("VPID CAP should not exist if not support " "1-setting enable VPID VM-execution control\n"); + + if (error_on_inconsistent_vmcs_config) + return -EIO; + + vmx_cap->vpid =3D 0; } =20 if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS) { @@ -2642,6 +2653,9 @@ static __init int setup_vmcs_config(struct vmcs_confi= g *vmcs_conf, pr_warn_once("Inconsistent VM-Entry/VM-Exit pair, entry =3D %x, exit =3D= %x\n", _vmentry_control & n_ctrl, _vmexit_control & x_ctrl); =20 + if (error_on_inconsistent_vmcs_config) + return -EIO; + _vmentry_control &=3D ~n_ctrl; _vmexit_control &=3D ~x_ctrl; } --=20 2.36.1.255.ge46751e96f-goog