* [PATCH 5.10.y 5.15.y 6.1.y 6.6.y] KVM: Replace guest-triggerable BUG_ON() in ioeventfd datamatch with get_unaligned()
@ 2026-07-07 22:47 Darshit Shah
2026-07-08 16:18 ` Sasha Levin
2026-07-08 16:30 ` [PATCH RESEND 5.10.y 5.15.y 6.1.y] " Darshit Shah
0 siblings, 2 replies; 4+ messages in thread
From: Darshit Shah @ 2026-07-07 22:47 UTC (permalink / raw)
To: stable
commit f1edbed787ba67988ed34e0132ca128b052b6ce8 upstream.
Drop a BUG_ON() that has been reachable since it was first added, way back
in 2009, and instead use get_unaligned() to perform potentially-unaligned
accesses.
For a given store, KVM x86's emulator tracks the entire value in the
destination operand, x86_emulate_ctxt.dst. If the destination is memory,
and the target splits multiple pages and/or is emulated MMIO, then KVM
handles each fragment independently. E.g. on a page split starting at page
offset 0xffc, KVM writes 4 bytes to the first page, then the remaining
bytes to the second page, using ctxt->dst as the source for both (with
appropriate offsets).
If the destination splits a page *and* hits emulated MMIO on the second
page, then KVM will complete the write to the first page, then emulate the
MMIO access to the second page. If there is a datamatch-enabled ioeventfd
at offset 0 of the second page, then KVM will process the remainder of the
store as a potential ioeventfd signal.
Putting it all together, if the guest emits a store that splits a page
starting at page offset N, and the second page has a datamatch-enabled
ioeventfd at offset 0, then KVM will check for datamatch using
&dst.valptr[N] as the source. Due to dst (and thus dst.valptr) being
32-byte aligned, if N is not aligned to @len, the BUG_ON() fires.
E.g. with a 16-byte store at page offset 0xffc, to an ioeventfd of len 8,
all initial checks in ioeventfd_in_range() will succeed, and the BUG_ON()
fires due to @val being 4-byte aligned, but not 8-byte aligned.
------------[ cut here ]------------
kernel BUG at arch/x86/kvm/../../../virt/kvm/eventfd.c:783!
Oops: invalid opcode: 0000 [#1] SMP
CPU: 0 UID: 1000 PID: 615 Comm: repro Not tainted 7.1.0-rc2-ff238429d1ea #365 PREEMPT
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
RIP: 0010:ioeventfd_write+0x6c/0x70 [kvm]
Call Trace:
<TASK>
__kvm_io_bus_write+0x85/0xb0 [kvm]
kvm_io_bus_write+0x53/0x80 [kvm]
vcpu_mmio_write+0x66/0xf0 [kvm]
emulator_read_write_onepage+0x12a/0x540 [kvm]
emulator_read_write+0x109/0x2b0 [kvm]
x86_emulate_insn+0x4f8/0xfb0 [kvm]
x86_emulate_instruction+0x181/0x790 [kvm]
kvm_mmu_page_fault+0x313/0x630 [kvm]
vmx_handle_exit+0x18a/0x590 [kvm_intel]
kvm_arch_vcpu_ioctl_run+0xc81/0x1c90 [kvm]
kvm_vcpu_ioctl+0x2d5/0x970 [kvm]
__x64_sys_ioctl+0x8a/0xd0
do_syscall_64+0xb7/0x890
entry_SYSCALL_64_after_hwframe+0x4b/0x53
RIP: 0033:0x7f19c931a9bf
</TASK>
Modules linked in: kvm_intel kvm irqbypass
---[ end trace 0000000000000000 ]---
In a perfect world, the fix would be to simply delete the BUG_ON(), as KVM
x86 doesn't perform alignment checks on "normal" memory accesses at CPL0.
Sadly, C99 ruins all the fun; while the x86 architecture plays nice,
dereferencing an unaligned pointer directly is undefined behavior in C,
e.g. triggers splats when running with CONFIG_UBSAN_ALIGNMENT=y.
Fixes: d34e6b175e61 ("KVM: add ioeventfd support")
Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-ID: <20260612225241.678509-1-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[ Use the old <asm/unaligned.h> header instead ]
Signed-off-by: Darshit Shah <darnshah@amazon.de>
---
virt/kvm/eventfd.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 4702b71aad08..ff0ef5f7246e 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <linux/seqlock.h>
#include <linux/irqbypass.h>
+#include <asm/unaligned.h>
#include <trace/events/kvm.h>
#include <kvm/iodev.h>
@@ -695,21 +696,18 @@ ioeventfd_in_range(struct _ioeventfd *p, gpa_t addr, int len, const void *val)
return true;
/* otherwise, we have to actually compare the data */
-
- BUG_ON(!IS_ALIGNED((unsigned long)val, len));
-
switch (len) {
case 1:
- _val = *(u8 *)val;
+ _val = get_unaligned((u8 *)val);
break;
case 2:
- _val = *(u16 *)val;
+ _val = get_unaligned((u16 *)val);
break;
case 4:
- _val = *(u32 *)val;
+ _val = get_unaligned((u32 *)val);
break;
case 8:
- _val = *(u64 *)val;
+ _val = get_unaligned((u64 *)val);
break;
default:
return false;
--
2.54.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH 5.10.y 5.15.y 6.1.y 6.6.y] KVM: Replace guest-triggerable BUG_ON() in ioeventfd datamatch with get_unaligned()
2026-07-07 22:47 [PATCH 5.10.y 5.15.y 6.1.y 6.6.y] KVM: Replace guest-triggerable BUG_ON() in ioeventfd datamatch with get_unaligned() Darshit Shah
@ 2026-07-08 16:18 ` Sasha Levin
2026-07-08 16:30 ` [PATCH RESEND 5.10.y 5.15.y 6.1.y] " Darshit Shah
1 sibling, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2026-07-08 16:18 UTC (permalink / raw)
To: stable; +Cc: Sasha Levin, Darshit Shah
On Tue, Jul 07, 2026 at 10:47:42PM +0000, Darshit Shah wrote:
> commit f1edbed787ba67988ed34e0132ca128b052b6ce8 upstream.
The backport content itself looks good (the asm/unaligned.h swap is the
right adaptation for these trees), but the mail is missing an in-body
"From:" line, so applying it records you as the commit author instead
of the upstream author. Could you resend with
From: Sean Christopherson <seanjc@google.com>
as the first line of the body so authorship is preserved?
Also note that 6.6.y already has this fix queued up, so the resend only
needs to target 6.1.y, 5.15.y, and 5.10.y.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH RESEND 5.10.y 5.15.y 6.1.y] KVM: Replace guest-triggerable BUG_ON() in ioeventfd datamatch with get_unaligned()
2026-07-07 22:47 [PATCH 5.10.y 5.15.y 6.1.y 6.6.y] KVM: Replace guest-triggerable BUG_ON() in ioeventfd datamatch with get_unaligned() Darshit Shah
2026-07-08 16:18 ` Sasha Levin
@ 2026-07-08 16:30 ` Darshit Shah
2026-07-09 1:04 ` Sasha Levin
1 sibling, 1 reply; 4+ messages in thread
From: Darshit Shah @ 2026-07-08 16:30 UTC (permalink / raw)
To: stable
From: Sean Christopherson <seanjc@google.com>
commit f1edbed787ba67988ed34e0132ca128b052b6ce8 upstream.
Drop a BUG_ON() that has been reachable since it was first added, way back
in 2009, and instead use get_unaligned() to perform potentially-unaligned
accesses.
For a given store, KVM x86's emulator tracks the entire value in the
destination operand, x86_emulate_ctxt.dst. If the destination is memory,
and the target splits multiple pages and/or is emulated MMIO, then KVM
handles each fragment independently. E.g. on a page split starting at page
offset 0xffc, KVM writes 4 bytes to the first page, then the remaining
bytes to the second page, using ctxt->dst as the source for both (with
appropriate offsets).
If the destination splits a page *and* hits emulated MMIO on the second
page, then KVM will complete the write to the first page, then emulate the
MMIO access to the second page. If there is a datamatch-enabled ioeventfd
at offset 0 of the second page, then KVM will process the remainder of the
store as a potential ioeventfd signal.
Putting it all together, if the guest emits a store that splits a page
starting at page offset N, and the second page has a datamatch-enabled
ioeventfd at offset 0, then KVM will check for datamatch using
&dst.valptr[N] as the source. Due to dst (and thus dst.valptr) being
32-byte aligned, if N is not aligned to @len, the BUG_ON() fires.
E.g. with a 16-byte store at page offset 0xffc, to an ioeventfd of len 8,
all initial checks in ioeventfd_in_range() will succeed, and the BUG_ON()
fires due to @val being 4-byte aligned, but not 8-byte aligned.
------------[ cut here ]------------
kernel BUG at arch/x86/kvm/../../../virt/kvm/eventfd.c:783!
Oops: invalid opcode: 0000 [#1] SMP
CPU: 0 UID: 1000 PID: 615 Comm: repro Not tainted 7.1.0-rc2-ff238429d1ea #365 PREEMPT
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
RIP: 0010:ioeventfd_write+0x6c/0x70 [kvm]
Call Trace:
<TASK>
__kvm_io_bus_write+0x85/0xb0 [kvm]
kvm_io_bus_write+0x53/0x80 [kvm]
vcpu_mmio_write+0x66/0xf0 [kvm]
emulator_read_write_onepage+0x12a/0x540 [kvm]
emulator_read_write+0x109/0x2b0 [kvm]
x86_emulate_insn+0x4f8/0xfb0 [kvm]
x86_emulate_instruction+0x181/0x790 [kvm]
kvm_mmu_page_fault+0x313/0x630 [kvm]
vmx_handle_exit+0x18a/0x590 [kvm_intel]
kvm_arch_vcpu_ioctl_run+0xc81/0x1c90 [kvm]
kvm_vcpu_ioctl+0x2d5/0x970 [kvm]
__x64_sys_ioctl+0x8a/0xd0
do_syscall_64+0xb7/0x890
entry_SYSCALL_64_after_hwframe+0x4b/0x53
RIP: 0033:0x7f19c931a9bf
</TASK>
Modules linked in: kvm_intel kvm irqbypass
---[ end trace 0000000000000000 ]---
In a perfect world, the fix would be to simply delete the BUG_ON(), as KVM
x86 doesn't perform alignment checks on "normal" memory accesses at CPL0.
Sadly, C99 ruins all the fun; while the x86 architecture plays nice,
dereferencing an unaligned pointer directly is undefined behavior in C,
e.g. triggers splats when running with CONFIG_UBSAN_ALIGNMENT=y.
Fixes: d34e6b175e61 ("KVM: add ioeventfd support")
Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-ID: <20260612225241.678509-1-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[ Use the old <asm/unaligned.h> header instead ]
Signed-off-by: Darshit Shah <darnshah@amazon.de>
---
virt/kvm/eventfd.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 4702b71aad08..ff0ef5f7246e 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <linux/seqlock.h>
#include <linux/irqbypass.h>
+#include <asm/unaligned.h>
#include <trace/events/kvm.h>
#include <kvm/iodev.h>
@@ -695,21 +696,18 @@ ioeventfd_in_range(struct _ioeventfd *p, gpa_t addr, int len, const void *val)
return true;
/* otherwise, we have to actually compare the data */
-
- BUG_ON(!IS_ALIGNED((unsigned long)val, len));
-
switch (len) {
case 1:
- _val = *(u8 *)val;
+ _val = get_unaligned((u8 *)val);
break;
case 2:
- _val = *(u16 *)val;
+ _val = get_unaligned((u16 *)val);
break;
case 4:
- _val = *(u32 *)val;
+ _val = get_unaligned((u32 *)val);
break;
case 8:
- _val = *(u64 *)val;
+ _val = get_unaligned((u64 *)val);
break;
default:
return false;
--
2.54.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH RESEND 5.10.y 5.15.y 6.1.y] KVM: Replace guest-triggerable BUG_ON() in ioeventfd datamatch with get_unaligned()
2026-07-08 16:30 ` [PATCH RESEND 5.10.y 5.15.y 6.1.y] " Darshit Shah
@ 2026-07-09 1:04 ` Sasha Levin
0 siblings, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2026-07-09 1:04 UTC (permalink / raw)
To: stable; +Cc: Sasha Levin, Darshit Shah
> From: Sean Christopherson <seanjc@google.com>
>
> commit f1edbed787ba67988ed34e0132ca128b052b6ce8 upstream.
>
> Drop a BUG_ON() that has been reachable since it was first added, way back
> in 2009, and instead use get_unaligned() to perform potentially-unaligned
> accesses.
Queued for 6.1, 5.15, and 5.10, thanks.
--
Thanks,
Sasha
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-09 1:04 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-07 22:47 [PATCH 5.10.y 5.15.y 6.1.y 6.6.y] KVM: Replace guest-triggerable BUG_ON() in ioeventfd datamatch with get_unaligned() Darshit Shah
2026-07-08 16:18 ` Sasha Levin
2026-07-08 16:30 ` [PATCH RESEND 5.10.y 5.15.y 6.1.y] " Darshit Shah
2026-07-09 1:04 ` Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox