Thanks Josh for a quick fix. Acked-by: Alexey Makhalov <[email protected]>
On 1/22/26 11:36 AM, Josh Poimboeuf wrote:
Fedora QA reported the following panic: BUG: unable to handle page fault for address: 0000000040003e54 #PF: supervisor write access in kernel mode #PF: error_code(0x0002) - not-present page PGD 1082ec067 P4D 0 Oops: Oops: 0002 [#1] SMP NOPTI CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.19.0-0.rc4.260108gf0b9d8eb98df.34.fc43.x86_64 #1 PREEMPT(lazy) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS edk2-20251119-3.fc43 11/19/2025 RIP: 0010:vmware_hypercall4.constprop.0+0x52/0x90 Code: 48 83 c4 20 5b e9 69 f0 fc fe 8b 05 a0 c1 b2 01 85 c0 74 23 b8 68 58 4d 56 b9 27 00 00 00 31 d2 bb 04 00 00 00 66 ba 58 56 ed <89> 1f 89 0e 41 89 10 5b e9 3c f0 fc fe 6a 00 49 89 f9 45 31 c0 31 RSP: 0018:ff5eeb3240003e40 EFLAGS: 00010046 RAX: 0000000000000000 RBX: 000000000000ffca RCX: 000000000000ffac RDX: 0000000000000000 RSI: 0000000040003e58 RDI: 0000000040003e54 RBP: ff1e05f3c1204800 R08: ff5eeb3240003e5c R09: 000000009d899c41 R10: 000000000000003d R11: ff5eeb3240003ff8 R12: 0000000000000000 R13: 00000000000000ff R14: ff1e05f3c02f9e00 R15: 000000000000000c FS: 0000000000000000(0000) GS:ff1e05f489e40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000040003e54 CR3: 000000010841d002 CR4: 0000000000771ef0 PKRU: 55555554 Call Trace: <IRQ> vmmouse_report_events+0x13e/0x1b0 psmouse_handle_byte+0x15/0x60 ps2_interrupt+0x8a/0xd0 ... The panic was triggered by dereferencing a bad pointer (RDI) immediately after a VMware hypercall for VMWARE_CMD_ABSPOINTER_DATA in the vmmouse driver: ffffffff82135070 <vmware_hypercall4.constprop.0>: ... ffffffff821350ac: b8 68 58 4d 56 mov $0x564d5868,%eax ffffffff821350b1: b9 27 00 00 00 mov $0x27,%ecx ffffffff821350b6: 31 d2 xor %edx,%edx ffffffff821350b8: bb 04 00 00 00 mov $0x4,%ebx ffffffff821350bd: 66 ba 58 56 mov $0x5658,%dx ffffffff821350c1: ed in (%dx),%eax <-- hypercall ffffffff821350c2: 89 1f mov %ebx,(%rdi) <-- crash Reading the disassembly shows that RDI should contain the value of a valid kernel stack address here (0xff5eeb3240003e54). Instead it contains 0x40003e54, suggesting the hypervisor cleared the upper 32 bits. And indeed, Alexey discovered that QEMU's vmmouse_get_data() and vmmouse_set_data() are only saving/restoring the lower 32 bits, while clearing the upper 32. Fix that by changing the type of the saved data array from uint32_t to target_ulong. Fixes: 548df2acc6fc ("VMMouse Emulation, by Anthony Liguori.") Reported-by: Justin Forbes <[email protected]> Debugged-by: Alexey Makhalov <[email protected]> Signed-off-by: Josh Poimboeuf <[email protected]> --- hw/i386/vmmouse.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/i386/vmmouse.c b/hw/i386/vmmouse.c index 2ae7f3a242..3bba221d5f 100644 --- a/hw/i386/vmmouse.c +++ b/hw/i386/vmmouse.c @@ -72,7 +72,7 @@ struct VMMouseState { ISAKBDState *i8042; };-static void vmmouse_get_data(uint32_t *data)+static void vmmouse_get_data(target_ulong *data) { X86CPU *cpu = X86_CPU(current_cpu); CPUX86State *env = &cpu->env; @@ -82,7 +82,7 @@ static void vmmouse_get_data(uint32_t *data) data[4] = env->regs[R_ESI]; data[5] = env->regs[R_EDI]; }-static void vmmouse_set_data(const uint32_t *data)+static void vmmouse_set_data(const target_ulong *data) { X86CPU *cpu = X86_CPU(current_cpu); CPUX86State *env = &cpu->env; @@ -197,7 +197,7 @@ static void vmmouse_disable(VMMouseState *s) vmmouse_remove_handler(s); }-static void vmmouse_data(VMMouseState *s, uint32_t *data, uint32_t size)+static void vmmouse_data(VMMouseState *s, target_ulong *data, uint32_t size) { int i;@@ -221,7 +221,7 @@ static void vmmouse_data(VMMouseState *s, uint32_t *data, uint32_t size)static uint32_t vmmouse_ioport_read(void *opaque, uint32_t addr) { VMMouseState *s = opaque; - uint32_t data[6]; + target_ulong data[6]; uint16_t command;vmmouse_get_data(data);@@ -247,7 +247,7 @@ static uint32_t vmmouse_ioport_read(void *opaque, uint32_t addr) vmmouse_request_absolute(s); break; default: - printf("vmmouse: unknown command %x\n", data[1]); + printf("vmmouse: unknown command " TARGET_FMT_lx "\n", data[1]); break; } break;
