From: Greg Kroah-Hartman Date: Mon, 18 Aug 2025 11:26:45 +0000 (+0200) Subject: 6.15-stable patches X-Git-Tag: v6.12.43~17 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b63bf59a0fe638397f8be53530c9c1d4dc1d466;p=thirdparty%2Fkernel%2Fstable-queue.git 6.15-stable patches 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 --- 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 index 0000000000..6b16860343 --- /dev/null +++ b/queue-6.15/kvm-nvmx-check-vmcs12-guest_ia32_debugctl-on-nested-vm-enter.patch @@ -0,0 +1,107 @@ +From 095686e6fcb4150f0a55b1a25987fad3d8af58d6 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Tue, 10 Jun 2025 16:20:08 -0700 +Subject: KVM: nVMX: Check vmcs12->guest_ia32_debugctl on nested VM-Enter + +From: Maxim Levitsky + +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 +Co-developed-by: Sean Christopherson +Link: https://lore.kernel.org/r/20250610232010.162191-7-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..385d9d4383 --- /dev/null +++ b/queue-6.15/kvm-vmx-extract-checking-of-guest-s-debugctl-into-helper.patch @@ -0,0 +1,85 @@ +From 8a4351ac302cd8c19729ba2636acfd0467c22ae8 Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Tue, 10 Jun 2025 16:20:07 -0700 +Subject: KVM: VMX: Extract checking of guest's DEBUGCTL into helper + +From: Sean Christopherson + +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 +Link: https://lore.kernel.org/r/20250610232010.162191-6-seanjc@google.com +Signed-off-by: Sean Christopherson +Stable-dep-of: 095686e6fcb4 ("KVM: nVMX: Check vmcs12->guest_ia32_debugctl on nested VM-Enter") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..c1fc47f8ae --- /dev/null +++ b/queue-6.15/kvm-vmx-wrap-all-accesses-to-ia32_debugctl-with-getter-setter-apis.patch @@ -0,0 +1,151 @@ +From 7d0cce6cbe71af6e9c1831bff101a2b9c249c4a2 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +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 + +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 +[sean: massage changelog, make inline, use in all prepare_vmcs02() cases] +Reviewed-by: Dapeng Mi +Link: https://lore.kernel.org/r/20250610232010.162191-8-seanjc@google.com +Signed-off-by: Sean Christopherson +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 diff --git a/queue-6.15/series b/queue-6.15/series index 81add39b72..39ff9ee7b6 100644 --- a/queue-6.15/series +++ b/queue-6.15/series @@ -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