Patch "KVM: x86: Make x2APIC ID 100% readonly" has been added to the 6.10-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    KVM: x86: Make x2APIC ID 100% readonly

to the 6.10-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     kvm-x86-make-x2apic-id-100-readonly.patch
and it can be found in the queue-6.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 4b84e6390a908a3653b1ae74c37856ea4da0a5c6
Author: Sean Christopherson <seanjc@xxxxxxxxxx>
Date:   Fri Aug 2 13:29:40 2024 -0700

    KVM: x86: Make x2APIC ID 100% readonly
    
    [ Upstream commit 4b7c3f6d04bd53f2e5b228b6821fb8f5d1ba3071 ]
    
    Ignore the userspace provided x2APIC ID when fixing up APIC state for
    KVM_SET_LAPIC, i.e. make the x2APIC fully readonly in KVM.  Commit
    a92e2543d6a8 ("KVM: x86: use hardware-compatible format for APIC ID
    register"), which added the fixup, didn't intend to allow userspace to
    modify the x2APIC ID.  In fact, that commit is when KVM first started
    treating the x2APIC ID as readonly, apparently to fix some race:
    
     static inline u32 kvm_apic_id(struct kvm_lapic *apic)
     {
    -       return (kvm_lapic_get_reg(apic, APIC_ID) >> 24) & 0xff;
    +       /* To avoid a race between apic_base and following APIC_ID update when
    +        * switching to x2apic_mode, the x2apic mode returns initial x2apic id.
    +        */
    +       if (apic_x2apic_mode(apic))
    +               return apic->vcpu->vcpu_id;
    +
    +       return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
     }
    
    Furthermore, KVM doesn't support delivering interrupts to vCPUs with a
    modified x2APIC ID, but KVM *does* return the modified value on a guest
    RDMSR and for KVM_GET_LAPIC.  I.e. no remotely sane setup can actually
    work with a modified x2APIC ID.
    
    Making the x2APIC ID fully readonly fixes a WARN in KVM's optimized map
    calculation, which expects the LDR to align with the x2APIC ID.
    
      WARNING: CPU: 2 PID: 958 at arch/x86/kvm/lapic.c:331 kvm_recalculate_apic_map+0x609/0xa00 [kvm]
      CPU: 2 PID: 958 Comm: recalc_apic_map Not tainted 6.4.0-rc3-vanilla+ #35
      Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.2-1-1 04/01/2014
      RIP: 0010:kvm_recalculate_apic_map+0x609/0xa00 [kvm]
      Call Trace:
       <TASK>
       kvm_apic_set_state+0x1cf/0x5b0 [kvm]
       kvm_arch_vcpu_ioctl+0x1806/0x2100 [kvm]
       kvm_vcpu_ioctl+0x663/0x8a0 [kvm]
       __x64_sys_ioctl+0xb8/0xf0
       do_syscall_64+0x56/0x80
       entry_SYSCALL_64_after_hwframe+0x46/0xb0
      RIP: 0033:0x7fade8b9dd6f
    
    Unfortunately, the WARN can still trigger for other CPUs than the current
    one by racing against KVM_SET_LAPIC, so remove it completely.
    
    Reported-by: Michal Luczaj <mhal@xxxxxxx>
    Closes: https://lore.kernel.org/all/814baa0c-1eaa-4503-129f-059917365e80@xxxxxxx
    Reported-by: Haoyu Wu <haoyuwu254@xxxxxxxxx>
    Closes: https://lore.kernel.org/all/20240126161633.62529-1-haoyuwu254@xxxxxxxxx
    Reported-by: syzbot+545f1326f405db4e1c3e@xxxxxxxxxxxxxxxxxxxxxxxxx
    Closes: https://lore.kernel.org/all/000000000000c2a6b9061cbca3c3@xxxxxxxxxx
    Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
    Message-ID: <20240802202941.344889-2-seanjc@xxxxxxxxxx>
    Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
    Stable-dep-of: 73b42dc69be8 ("KVM: x86: Re-split x2APIC ICR into ICR+ICR2 for AMD (x2AVIC)")
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index f1f54218b0603..9392d6e3d8e37 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -351,10 +351,8 @@ static void kvm_recalculate_logical_map(struct kvm_apic_map *new,
 	 * reversing the LDR calculation to get cluster of APICs, i.e. no
 	 * additional work is required.
 	 */
-	if (apic_x2apic_mode(apic)) {
-		WARN_ON_ONCE(ldr != kvm_apic_calc_x2apic_ldr(kvm_x2apic_id(apic)));
+	if (apic_x2apic_mode(apic))
 		return;
-	}
 
 	if (WARN_ON_ONCE(!kvm_apic_map_get_logical_dest(new, ldr,
 							&cluster, &mask))) {
@@ -2987,18 +2985,28 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
 		struct kvm_lapic_state *s, bool set)
 {
 	if (apic_x2apic_mode(vcpu->arch.apic)) {
+		u32 x2apic_id = kvm_x2apic_id(vcpu->arch.apic);
 		u32 *id = (u32 *)(s->regs + APIC_ID);
 		u32 *ldr = (u32 *)(s->regs + APIC_LDR);
 		u64 icr;
 
 		if (vcpu->kvm->arch.x2apic_format) {
-			if (*id != vcpu->vcpu_id)
+			if (*id != x2apic_id)
 				return -EINVAL;
 		} else {
+			/*
+			 * Ignore the userspace value when setting APIC state.
+			 * KVM's model is that the x2APIC ID is readonly, e.g.
+			 * KVM only supports delivering interrupts to KVM's
+			 * version of the x2APIC ID.  However, for backwards
+			 * compatibility, don't reject attempts to set a
+			 * mismatched ID for userspace that hasn't opted into
+			 * x2apic_format.
+			 */
 			if (set)
-				*id >>= 24;
+				*id = x2apic_id;
 			else
-				*id <<= 24;
+				*id = x2apic_id << 24;
 		}
 
 		/*
@@ -3007,7 +3015,7 @@ static int kvm_apic_state_fixup(struct kvm_vcpu *vcpu,
 		 * split to ICR+ICR2 in userspace for backwards compatibility.
 		 */
 		if (set) {
-			*ldr = kvm_apic_calc_x2apic_ldr(*id);
+			*ldr = kvm_apic_calc_x2apic_ldr(x2apic_id);
 
 			icr = __kvm_lapic_get_reg(s->regs, APIC_ICR) |
 			      (u64)__kvm_lapic_get_reg(s->regs, APIC_ICR2) << 32;




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux