From: David Woodhouse Xen enforces that the vcpu_info GPA is aligned to sizeof(xen_ulong_t) (8 bytes in 64-bit mode, 4 bytes in 32-bit mode) in map_guest_area(). KVM has no such check, allowing a guest to register a vcpu_info at an arbitrary byte alignment. This can cause split-lock #AC exceptions on hosts with split_lock_detect=fatal, since the event channel delivery paths use locked atomic operations on evtchn_pending_sel within the vcpu_info. Add the same alignment check that Xen performs at vcpu_info registration time, based on the current long_mode state. Return -ENXIO on failure, matching Xen's map_guest_area() behaviour for unaligned requests. Like Xen, this allows a guest to register vcpu_info at a 4-byte (but not 8-byte) aligned address while in 32-bit mode and then switch to 64-bit mode. Xen copes with this because it only uses 32-bit atomics on vcpu_info fields, which is what subsequent commits will do where necessary for KVM too. Originally observed in review of an unrelated patch: https://lore.kernel.org/all/20260604193554.1BA311F00893@smtp.kernel.org/ Cc: stable@vger.kernel.org Fixes: 73e69a86347a ("KVM: x86/xen: register vcpu info") Reported-by: sashiko-bot@kernel.org Assisted-by: Kiro:claude-opus-4.6-1m Signed-off-by: David Woodhouse --- arch/x86/kvm/xen.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c index f9085612e7df..ae0713718367 100644 --- a/arch/x86/kvm/xen.c +++ b/arch/x86/kvm/xen.c @@ -926,6 +926,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) break; } + r = -ENXIO; + if (!IS_ALIGNED(data->u.gpa, + kvm_xen_has_64bit_shinfo(vcpu->kvm) ? + sizeof(unsigned long) : sizeof(u32))) + break; + r = kvm_gpc_activate(&vcpu->arch.xen.vcpu_info_cache, data->u.gpa, sizeof(struct vcpu_info)); } else { @@ -935,6 +941,12 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) break; } + r = -ENXIO; + if (!IS_ALIGNED(data->u.hva, + kvm_xen_has_64bit_shinfo(vcpu->kvm) ? + sizeof(unsigned long) : sizeof(u32))) + break; + r = kvm_gpc_activate_hva(&vcpu->arch.xen.vcpu_info_cache, data->u.hva, sizeof(struct vcpu_info)); } -- 2.54.0