]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 18 Aug 2025 11:26:45 +0000 (13:26 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 18 Aug 2025 11:26:45 +0000 (13:26 +0200)
added patches:
kvm-nvmx-check-vmcs12-guest_ia32_debugctl-on-nested-vm-enter.patch
kvm-vmx-extract-checking-of-guest-s-debugctl-into-helper.patch
kvm-vmx-wrap-all-accesses-to-ia32_debugctl-with-getter-setter-apis.patch

queue-6.15/kvm-nvmx-check-vmcs12-guest_ia32_debugctl-on-nested-vm-enter.patch [new file with mode: 0644]
queue-6.15/kvm-vmx-extract-checking-of-guest-s-debugctl-into-helper.patch [new file with mode: 0644]
queue-6.15/kvm-vmx-wrap-all-accesses-to-ia32_debugctl-with-getter-setter-apis.patch [new file with mode: 0644]
queue-6.15/series

diff --git a/queue-6.15/kvm-nvmx-check-vmcs12-guest_ia32_debugctl-on-nested-vm-enter.patch b/queue-6.15/kvm-nvmx-check-vmcs12-guest_ia32_debugctl-on-nested-vm-enter.patch
new file mode 100644 (file)
index 0000000..6b16860
--- /dev/null
@@ -0,0 +1,107 @@
+From 095686e6fcb4150f0a55b1a25987fad3d8af58d6 Mon Sep 17 00:00:00 2001
+From: Maxim Levitsky <mlevitsk@redhat.com>
+Date: Tue, 10 Jun 2025 16:20:08 -0700
+Subject: KVM: nVMX: Check vmcs12->guest_ia32_debugctl on nested VM-Enter
+
+From: Maxim Levitsky <mlevitsk@redhat.com>
+
+commit 095686e6fcb4150f0a55b1a25987fad3d8af58d6 upstream.
+
+Add a consistency check for L2's guest_ia32_debugctl, as KVM only supports
+a subset of hardware functionality, i.e. KVM can't rely on hardware to
+detect illegal/unsupported values.  Failure to check the vmcs12 value
+would allow the guest to load any harware-supported value while running L2.
+
+Take care to exempt BTF and LBR from the validity check in order to match
+KVM's behavior for writes via WRMSR, but without clobbering vmcs12.  Even
+if VM_EXIT_SAVE_DEBUG_CONTROLS is set in vmcs12, L1 can reasonably expect
+that vmcs12->guest_ia32_debugctl will not be modified if writes to the MSR
+are being intercepted.
+
+Arguably, KVM _should_ update vmcs12 if VM_EXIT_SAVE_DEBUG_CONTROLS is set
+*and* writes to MSR_IA32_DEBUGCTLMSR are not being intercepted by L1, but
+that would incur non-trivial complexity and wouldn't change the fact that
+KVM's handling of DEBUGCTL is blatantly broken.  I.e. the extra complexity
+is not worth carrying.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
+Co-developed-by: Sean Christopherson <seanjc@google.com>
+Link: https://lore.kernel.org/r/20250610232010.162191-7-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/vmx/nested.c |   12 ++++++++++--
+ arch/x86/kvm/vmx/vmx.c    |    5 ++---
+ arch/x86/kvm/vmx/vmx.h    |    3 +++
+ 3 files changed, 15 insertions(+), 5 deletions(-)
+
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -2653,7 +2653,8 @@ static int prepare_vmcs02(struct kvm_vcp
+       if (vmx->nested.nested_run_pending &&
+           (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) {
+               kvm_set_dr(vcpu, 7, vmcs12->guest_dr7);
+-              vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl);
++              vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl &
++                                                vmx_get_supported_debugctl(vcpu, false));
+       } else {
+               kvm_set_dr(vcpu, 7, vcpu->arch.dr7);
+               vmcs_write64(GUEST_IA32_DEBUGCTL, vmx->nested.pre_vmenter_debugctl);
+@@ -3146,7 +3147,8 @@ static int nested_vmx_check_guest_state(
+               return -EINVAL;
+       if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS) &&
+-          CC(!kvm_dr7_valid(vmcs12->guest_dr7)))
++          (CC(!kvm_dr7_valid(vmcs12->guest_dr7)) ||
++           CC(!vmx_is_valid_debugctl(vcpu, vmcs12->guest_ia32_debugctl, false))))
+               return -EINVAL;
+       if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT) &&
+@@ -4598,6 +4600,12 @@ static void sync_vmcs02_to_vmcs12(struct
+               (vmcs12->vm_entry_controls & ~VM_ENTRY_IA32E_MODE) |
+               (vm_entry_controls_get(to_vmx(vcpu)) & VM_ENTRY_IA32E_MODE);
++      /*
++       * Note!  Save DR7, but intentionally don't grab DEBUGCTL from vmcs02.
++       * Writes to DEBUGCTL that aren't intercepted by L1 are immediately
++       * propagated to vmcs12 (see vmx_set_msr()), as the value loaded into
++       * vmcs02 doesn't strictly track vmcs12.
++       */
+       if (vmcs12->vm_exit_controls & VM_EXIT_SAVE_DEBUG_CONTROLS)
+               vmcs12->guest_dr7 = vcpu->arch.dr7;
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -2180,7 +2180,7 @@ static u64 nested_vmx_truncate_sysenter_
+       return (unsigned long)data;
+ }
+-static u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated)
++u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated)
+ {
+       u64 debugctl = 0;
+@@ -2199,8 +2199,7 @@ static u64 vmx_get_supported_debugctl(st
+       return debugctl;
+ }
+-static bool vmx_is_valid_debugctl(struct kvm_vcpu *vcpu, u64 data,
+-                                bool host_initiated)
++bool vmx_is_valid_debugctl(struct kvm_vcpu *vcpu, u64 data, bool host_initiated)
+ {
+       u64 invalid;
+--- a/arch/x86/kvm/vmx/vmx.h
++++ b/arch/x86/kvm/vmx/vmx.h
+@@ -437,6 +437,9 @@ static inline void vmx_set_intercept_for
+ void vmx_update_cpu_dirty_logging(struct kvm_vcpu *vcpu);
++u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated);
++bool vmx_is_valid_debugctl(struct kvm_vcpu *vcpu, u64 data, bool host_initiated);
++
+ /*
+  * Note, early Intel manuals have the write-low and read-high bitmap offsets
+  * the wrong way round.  The bitmaps control MSRs 0x00000000-0x00001fff and
diff --git a/queue-6.15/kvm-vmx-extract-checking-of-guest-s-debugctl-into-helper.patch b/queue-6.15/kvm-vmx-extract-checking-of-guest-s-debugctl-into-helper.patch
new file mode 100644 (file)
index 0000000..385d9d4
--- /dev/null
@@ -0,0 +1,85 @@
+From 8a4351ac302cd8c19729ba2636acfd0467c22ae8 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Tue, 10 Jun 2025 16:20:07 -0700
+Subject: KVM: VMX: Extract checking of guest's DEBUGCTL into helper
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 8a4351ac302cd8c19729ba2636acfd0467c22ae8 upstream.
+
+Move VMX's logic to check DEBUGCTL values into a standalone helper so that
+the code can be used by nested VM-Enter to apply the same logic to the
+value being loaded from vmcs12.
+
+KVM needs to explicitly check vmcs12->guest_ia32_debugctl on nested
+VM-Enter, as hardware may support features that KVM does not, i.e. relying
+on hardware to detect invalid guest state will result in false negatives.
+Unfortunately, that means applying KVM's funky suppression of BTF and LBR
+to vmcs12 so as not to break existing guests.
+
+No functional change intended.
+
+Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
+Link: https://lore.kernel.org/r/20250610232010.162191-6-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Stable-dep-of: 095686e6fcb4 ("KVM: nVMX: Check vmcs12->guest_ia32_debugctl on nested VM-Enter")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/vmx/vmx.c |   29 +++++++++++++++++------------
+ 1 file changed, 17 insertions(+), 12 deletions(-)
+
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -2199,6 +2199,19 @@ static u64 vmx_get_supported_debugctl(st
+       return debugctl;
+ }
++static bool vmx_is_valid_debugctl(struct kvm_vcpu *vcpu, u64 data,
++                                bool host_initiated)
++{
++      u64 invalid;
++
++      invalid = data & ~vmx_get_supported_debugctl(vcpu, host_initiated);
++      if (invalid & (DEBUGCTLMSR_BTF | DEBUGCTLMSR_LBR)) {
++              kvm_pr_unimpl_wrmsr(vcpu, MSR_IA32_DEBUGCTLMSR, data);
++              invalid &= ~(DEBUGCTLMSR_BTF | DEBUGCTLMSR_LBR);
++      }
++      return !invalid;
++}
++
+ /*
+  * Writes msr value into the appropriate "register".
+  * Returns 0 on success, non-0 otherwise.
+@@ -2267,19 +2280,12 @@ int vmx_set_msr(struct kvm_vcpu *vcpu, s
+               }
+               vmcs_writel(GUEST_SYSENTER_ESP, data);
+               break;
+-      case MSR_IA32_DEBUGCTLMSR: {
+-              u64 invalid;
+-
+-              invalid = data & ~vmx_get_supported_debugctl(vcpu, msr_info->host_initiated);
+-              if (invalid & (DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR)) {
+-                      kvm_pr_unimpl_wrmsr(vcpu, msr_index, data);
+-                      data &= ~(DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR);
+-                      invalid &= ~(DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR);
+-              }
+-
+-              if (invalid)
++      case MSR_IA32_DEBUGCTLMSR:
++              if (!vmx_is_valid_debugctl(vcpu, data, msr_info->host_initiated))
+                       return 1;
++              data &= vmx_get_supported_debugctl(vcpu, msr_info->host_initiated);
++
+               if (is_guest_mode(vcpu) && get_vmcs12(vcpu)->vm_exit_controls &
+                                               VM_EXIT_SAVE_DEBUG_CONTROLS)
+                       get_vmcs12(vcpu)->guest_ia32_debugctl = data;
+@@ -2289,7 +2295,6 @@ int vmx_set_msr(struct kvm_vcpu *vcpu, s
+                   (data & DEBUGCTLMSR_LBR))
+                       intel_pmu_create_guest_lbr_event(vcpu);
+               return 0;
+-      }
+       case MSR_IA32_BNDCFGS:
+               if (!kvm_mpx_supported() ||
+                   (!msr_info->host_initiated &&
diff --git a/queue-6.15/kvm-vmx-wrap-all-accesses-to-ia32_debugctl-with-getter-setter-apis.patch b/queue-6.15/kvm-vmx-wrap-all-accesses-to-ia32_debugctl-with-getter-setter-apis.patch
new file mode 100644 (file)
index 0000000..c1fc47f
--- /dev/null
@@ -0,0 +1,151 @@
+From 7d0cce6cbe71af6e9c1831bff101a2b9c249c4a2 Mon Sep 17 00:00:00 2001
+From: Maxim Levitsky <mlevitsk@redhat.com>
+Date: Tue, 10 Jun 2025 16:20:09 -0700
+Subject: KVM: VMX: Wrap all accesses to IA32_DEBUGCTL with getter/setter APIs
+
+From: Maxim Levitsky <mlevitsk@redhat.com>
+
+commit 7d0cce6cbe71af6e9c1831bff101a2b9c249c4a2 upstream.
+
+Introduce vmx_guest_debugctl_{read,write}() to handle all accesses to
+vmcs.GUEST_IA32_DEBUGCTL. This will allow stuffing FREEZE_IN_SMM into
+GUEST_IA32_DEBUGCTL based on the host setting without bleeding the state
+into the guest, and without needing to copy+paste the FREEZE_IN_SMM
+logic into every patch that accesses GUEST_IA32_DEBUGCTL.
+
+No functional change intended.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
+[sean: massage changelog, make inline, use in all prepare_vmcs02() cases]
+Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
+Link: https://lore.kernel.org/r/20250610232010.162191-8-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/vmx/nested.c    |   10 +++++-----
+ arch/x86/kvm/vmx/pmu_intel.c |    8 ++++----
+ arch/x86/kvm/vmx/vmx.c       |    8 +++++---
+ arch/x86/kvm/vmx/vmx.h       |   10 ++++++++++
+ 4 files changed, 24 insertions(+), 12 deletions(-)
+
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -2653,11 +2653,11 @@ static int prepare_vmcs02(struct kvm_vcp
+       if (vmx->nested.nested_run_pending &&
+           (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) {
+               kvm_set_dr(vcpu, 7, vmcs12->guest_dr7);
+-              vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl &
+-                                                vmx_get_supported_debugctl(vcpu, false));
++              vmx_guest_debugctl_write(vcpu, vmcs12->guest_ia32_debugctl &
++                                             vmx_get_supported_debugctl(vcpu, false));
+       } else {
+               kvm_set_dr(vcpu, 7, vcpu->arch.dr7);
+-              vmcs_write64(GUEST_IA32_DEBUGCTL, vmx->nested.pre_vmenter_debugctl);
++              vmx_guest_debugctl_write(vcpu, vmx->nested.pre_vmenter_debugctl);
+       }
+       if (kvm_mpx_supported() && (!vmx->nested.nested_run_pending ||
+           !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)))
+@@ -3522,7 +3522,7 @@ enum nvmx_vmentry_status nested_vmx_ente
+       if (!vmx->nested.nested_run_pending ||
+           !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
+-              vmx->nested.pre_vmenter_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
++              vmx->nested.pre_vmenter_debugctl = vmx_guest_debugctl_read();
+       if (kvm_mpx_supported() &&
+           (!vmx->nested.nested_run_pending ||
+            !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)))
+@@ -4796,7 +4796,7 @@ static void load_vmcs12_host_state(struc
+       __vmx_set_segment(vcpu, &seg, VCPU_SREG_LDTR);
+       kvm_set_dr(vcpu, 7, 0x400);
+-      vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
++      vmx_guest_debugctl_write(vcpu, 0);
+       if (nested_vmx_load_msr(vcpu, vmcs12->vm_exit_msr_load_addr,
+                               vmcs12->vm_exit_msr_load_count))
+--- a/arch/x86/kvm/vmx/pmu_intel.c
++++ b/arch/x86/kvm/vmx/pmu_intel.c
+@@ -605,11 +605,11 @@ static void intel_pmu_reset(struct kvm_v
+  */
+ static void intel_pmu_legacy_freezing_lbrs_on_pmi(struct kvm_vcpu *vcpu)
+ {
+-      u64 data = vmcs_read64(GUEST_IA32_DEBUGCTL);
++      u64 data = vmx_guest_debugctl_read();
+       if (data & DEBUGCTLMSR_FREEZE_LBRS_ON_PMI) {
+               data &= ~DEBUGCTLMSR_LBR;
+-              vmcs_write64(GUEST_IA32_DEBUGCTL, data);
++              vmx_guest_debugctl_write(vcpu, data);
+       }
+ }
+@@ -679,7 +679,7 @@ void vmx_passthrough_lbr_msrs(struct kvm
+       if (!lbr_desc->event) {
+               vmx_disable_lbr_msrs_passthrough(vcpu);
+-              if (vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR)
++              if (vmx_guest_debugctl_read() & DEBUGCTLMSR_LBR)
+                       goto warn;
+               if (test_bit(INTEL_PMC_IDX_FIXED_VLBR, pmu->pmc_in_use))
+                       goto warn;
+@@ -701,7 +701,7 @@ warn:
+ static void intel_pmu_cleanup(struct kvm_vcpu *vcpu)
+ {
+-      if (!(vmcs_read64(GUEST_IA32_DEBUGCTL) & DEBUGCTLMSR_LBR))
++      if (!(vmx_guest_debugctl_read() & DEBUGCTLMSR_LBR))
+               intel_pmu_release_guest_lbr_event(vcpu);
+ }
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -2155,7 +2155,7 @@ int vmx_get_msr(struct kvm_vcpu *vcpu, s
+                       msr_info->data = vmx->pt_desc.guest.addr_a[index / 2];
+               break;
+       case MSR_IA32_DEBUGCTLMSR:
+-              msr_info->data = vmcs_read64(GUEST_IA32_DEBUGCTL);
++              msr_info->data = vmx_guest_debugctl_read();
+               break;
+       default:
+       find_uret_msr:
+@@ -2289,7 +2289,8 @@ int vmx_set_msr(struct kvm_vcpu *vcpu, s
+                                               VM_EXIT_SAVE_DEBUG_CONTROLS)
+                       get_vmcs12(vcpu)->guest_ia32_debugctl = data;
+-              vmcs_write64(GUEST_IA32_DEBUGCTL, data);
++              vmx_guest_debugctl_write(vcpu, data);
++
+               if (intel_pmu_lbr_is_enabled(vcpu) && !to_vmx(vcpu)->lbr_desc.event &&
+                   (data & DEBUGCTLMSR_LBR))
+                       intel_pmu_create_guest_lbr_event(vcpu);
+@@ -4861,7 +4862,8 @@ static void init_vmcs(struct vcpu_vmx *v
+       vmcs_write32(GUEST_SYSENTER_CS, 0);
+       vmcs_writel(GUEST_SYSENTER_ESP, 0);
+       vmcs_writel(GUEST_SYSENTER_EIP, 0);
+-      vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
++
++      vmx_guest_debugctl_write(&vmx->vcpu, 0);
+       if (cpu_has_vmx_tpr_shadow()) {
+               vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, 0);
+--- a/arch/x86/kvm/vmx/vmx.h
++++ b/arch/x86/kvm/vmx/vmx.h
+@@ -440,6 +440,16 @@ void vmx_update_cpu_dirty_logging(struct
+ u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated);
+ bool vmx_is_valid_debugctl(struct kvm_vcpu *vcpu, u64 data, bool host_initiated);
++static inline void vmx_guest_debugctl_write(struct kvm_vcpu *vcpu, u64 val)
++{
++      vmcs_write64(GUEST_IA32_DEBUGCTL, val);
++}
++
++static inline u64 vmx_guest_debugctl_read(void)
++{
++      return vmcs_read64(GUEST_IA32_DEBUGCTL);
++}
++
+ /*
+  * Note, early Intel manuals have the write-low and read-high bitmap offsets
+  * the wrong way round.  The bitmaps control MSRs 0x00000000-0x00001fff and
index 81add39b7240f6c559194be3b635ba9014fa277f..39ff9ee7b61f18a1e45a5b0f5be50665e1511a34 100644 (file)
@@ -500,3 +500,6 @@ media-v4l2-add-support-for-nv12m-tiled-variants-to-v4l2_format_info.patch
 tracing-fprobe-fix-infinite-recursion-using-preempt_-_notrace.patch
 tools-nolibc-fix-spelling-of-fd_setbitmask-in-fd_-macros.patch
 rdma-siw-fix-the-sendmsg-byte-count-in-siw_tcp_sendpages.patch
+kvm-vmx-extract-checking-of-guest-s-debugctl-into-helper.patch
+kvm-nvmx-check-vmcs12-guest_ia32_debugctl-on-nested-vm-enter.patch
+kvm-vmx-wrap-all-accesses-to-ia32_debugctl-with-getter-setter-apis.patch