[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <73641ce4-9387-48c6-8904-74997f9bb7ac@leemhuis.info>
Date: Fri, 23 Jan 2026 10:47:18 +0100
From: Thorsten Leemhuis <regressions@...mhuis.info>
To: Alexey Makhalov <alexey.makhalov@...adcom.com>,
Josh Poimboeuf <jpoimboe@...nel.org>, x86@...nel.org
Cc: linux-kernel@...r.kernel.org, Ajay Kaher <ajay.kaher@...adcom.com>,
bcm-kernel-feedback-list@...adcom.com, Peter Zijlstra
<peterz@...radead.org>, Justin Forbes <jforbes@...oraproject.org>,
Linux kernel regressions list <regressions@...ts.linux.dev>
Subject: Re: [PATCH] x86/vmware: Fix hypercall clobbers
[CCing the regression list]
On 1/22/26 11:00, Alexey Makhalov wrote:
>
> Thanks for reporting the problem.
> [...]
> Workarounding QEMU misbehavior from the kernel side by introducing less
> efficient asm inlines does not sound correct.
Well, fixing bugs right where they are obviously is a good thing.
But well, the problem according to the description quoted below was
exposed by a change that went into 6.19-rc1 -- which makes it a kernel
regression that must be fixed in the kernel (ideally before 6.19 is out).
At least from my understanding of Linus point of view on situations like
that. Or am I mistaken for some reason?
Or is this a case of "we for now assume this is such a corner case that
nobody else will hit; if we are wrong we'll reconsider".
Ciao, Thorsten
> Please report or fix the issue from QEMU side.
> Recommended QEMU fix: vmmouse_get_data/vmmouse_set_data should save/
> restore target_ulong type instead of uint32_t.
>
> Regards,
> --Alexey
>
> On 1/21/26 7:18 PM, 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 (in RDI)
>> immediately after a VMware hypercall:
>>
>> 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.
>>
>> This issue was bisected to commit aca282ab7e75 ("x86/asm: Annotate
>> special section entries"), which added annotations to the ALTERNATIVE()
>> macro. Despite the use of asm_inline, that commit caused the compiler
>> to un-inline and const-propagate vmware_hypercall4().
>>
>> That made RDI live across the hypercall, making the hypervisor's
>> register clobbering visible and exposing this latent bug.
>>
>> The open-vm-tools reference implementation treats all six registers as
>> clobbered for all hypercalls. Match that behavior here.
>>
>> Fixes: 34bf25e820ae ("x86/vmware: Introduce VMware hypercall API")
>> Fixes: aca282ab7e75 ("x86/asm: Annotate special section entries")
>> Reported-by: Justin Forbes <jforbes@...oraproject.org>
>> Signed-off-by: Josh Poimboeuf <jpoimboe@...nel.org>
>> ---
>> arch/x86/include/asm/vmware.h | 72 +++++++++++++++++------------------
>> 1 file changed, 34 insertions(+), 38 deletions(-)
>>
>> diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/
>> vmware.h
>> index c9cf43d5ef23..372173d4ea27 100644
>> --- a/arch/x86/include/asm/vmware.h
>> +++ b/arch/x86/include/asm/vmware.h
>> @@ -98,7 +98,7 @@ extern unsigned long vmware_tdx_hypercall(unsigned
>> long cmd,
>> static inline
>> unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
>> {
>> - unsigned long out0;
>> + unsigned long out0, tmp = 0;
>> if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
>> return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
>> @@ -109,13 +109,11 @@ unsigned long vmware_hypercall1(unsigned long
>> cmd, unsigned long in1)
>> NULL, NULL, NULL, NULL, NULL);
>> asm_inline volatile (VMWARE_HYPERCALL
>> - : "=a" (out0)
>> + : "=a" (out0), "+b" (in1), "+c" (cmd), "+d" (tmp)
>> : [port] "i" (VMWARE_HYPERVISOR_PORT),
>> - "a" (VMWARE_HYPERVISOR_MAGIC),
>> - "b" (in1),
>> - "c" (cmd),
>> - "d" (0)
>> - : "cc", "memory");
>> + "a" (VMWARE_HYPERVISOR_MAGIC)
>> + : "di", "si", "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -123,7 +121,7 @@ static inline
>> unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
>> u32 *out1, u32 *out2)
>> {
>> - unsigned long out0;
>> + unsigned long out0, tmp = 0;
>> if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
>> return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
>> @@ -134,13 +132,13 @@ unsigned long vmware_hypercall3(unsigned long
>> cmd, unsigned long in1,
>> out1, out2, NULL, NULL, NULL);
>> asm_inline volatile (VMWARE_HYPERCALL
>> - : "=a" (out0), "=b" (*out1), "=c" (*out2)
>> + : "=a" (out0), "=b" (*out1), "=c" (*out2), "+d" (tmp)
>> : [port] "i" (VMWARE_HYPERVISOR_PORT),
>> "a" (VMWARE_HYPERVISOR_MAGIC),
>> "b" (in1),
>> - "c" (cmd),
>> - "d" (0)
>> - : "cc", "memory");
>> + "c" (cmd)
>> + : "di", "si", "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -165,7 +163,8 @@ unsigned long vmware_hypercall4(unsigned long
>> cmd, unsigned long in1,
>> "b" (in1),
>> "c" (cmd),
>> "d" (0)
>> - : "cc", "memory");
>> + : "di", "si", "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -185,15 +184,13 @@ unsigned long vmware_hypercall5(unsigned long
>> cmd, unsigned long in1,
>> NULL, out2, NULL, NULL, NULL);
>> asm_inline volatile (VMWARE_HYPERCALL
>> - : "=a" (out0), "=c" (*out2)
>> + : "=a" (out0), "+b" (in1), "=c" (*out2), "+d" (in3),
>> + "+S" (in4), "+D" (in5)
>> : [port] "i" (VMWARE_HYPERVISOR_PORT),
>> "a" (VMWARE_HYPERVISOR_MAGIC),
>> - "b" (in1),
>> - "c" (cmd),
>> - "d" (in3),
>> - "S" (in4),
>> - "D" (in5)
>> + "c" (cmd)
>> : "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -213,14 +210,14 @@ unsigned long vmware_hypercall6(unsigned long
>> cmd, unsigned long in1,
>> NULL, out2, out3, out4, out5);
>> asm_inline volatile (VMWARE_HYPERCALL
>> - : "=a" (out0), "=c" (*out2), "=d" (*out3), "=S" (*out4),
>> - "=D" (*out5)
>> + : "=a" (out0), "+b" (in1), "=c" (*out2), "=d" (*out3),
>> + "=S" (*out4), "=D" (*out5)
>> : [port] "i" (VMWARE_HYPERVISOR_PORT),
>> "a" (VMWARE_HYPERVISOR_MAGIC),
>> - "b" (in1),
>> "c" (cmd),
>> "d" (in3)
>> : "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -241,15 +238,15 @@ unsigned long vmware_hypercall7(unsigned long
>> cmd, unsigned long in1,
>> out1, out2, out3, NULL, NULL);
>> asm_inline volatile (VMWARE_HYPERCALL
>> - : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3)
>> + : "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3),
>> + "+S" (in4), "+D" (in5)
>> : [port] "i" (VMWARE_HYPERVISOR_PORT),
>> "a" (VMWARE_HYPERVISOR_MAGIC),
>> "b" (in1),
>> "c" (cmd),
>> - "d" (in3),
>> - "S" (in4),
>> - "D" (in5)
>> + "d" (in3)
>> : "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -272,7 +269,9 @@ unsigned long vmware_hypercall_hb_out(unsigned
>> long cmd, unsigned long in2,
>> unsigned long in5, unsigned long in6,
>> u32 *out1)
>> {
>> - unsigned long out0;
>> + unsigned long out0, port;
>> +
>> + port = in3 | VMWARE_HYPERVISOR_PORT_HB;
>> asm_inline volatile (
>> UNWIND_HINT_SAVE
>> @@ -282,15 +281,13 @@ unsigned long vmware_hypercall_hb_out(unsigned
>> long cmd, unsigned long in2,
>> "rep outsb\n\t"
>> "pop %%" _ASM_BP "\n\t"
>> UNWIND_HINT_RESTORE
>> - : "=a" (out0), "=b" (*out1)
>> + : "=a" (out0), "=b" (*out1), "+c" (in2), "+d" (port),
>> + "+S" (in4), "+D" (in5)
>> : "a" (VMWARE_HYPERVISOR_MAGIC),
>> "b" (cmd),
>> - "c" (in2),
>> - "d" (in3 | VMWARE_HYPERVISOR_PORT_HB),
>> - "S" (in4),
>> - "D" (in5),
>> [in6] VMW_BP_CONSTRAINT (in6)
>> : "cc", "memory");
>> +
>> return out0;
>> }
>> @@ -300,7 +297,9 @@ unsigned long vmware_hypercall_hb_in(unsigned
>> long cmd, unsigned long in2,
>> unsigned long in5, unsigned long in6,
>> u32 *out1)
>> {
>> - unsigned long out0;
>> + unsigned long out0, port;
>> +
>> + port = in3 | VMWARE_HYPERVISOR_PORT_HB;
>> asm_inline volatile (
>> UNWIND_HINT_SAVE
>> @@ -310,13 +309,10 @@ unsigned long vmware_hypercall_hb_in(unsigned
>> long cmd, unsigned long in2,
>> "rep insb\n\t"
>> "pop %%" _ASM_BP "\n\t"
>> UNWIND_HINT_RESTORE
>> - : "=a" (out0), "=b" (*out1)
>> + : "=a" (out0), "=b" (*out1), "+c" (in2), "+d" (port),
>> + "+S" (in4), "+D" (in5)
>> : "a" (VMWARE_HYPERVISOR_MAGIC),
>> "b" (cmd),
>> - "c" (in2),
>> - "d" (in3 | VMWARE_HYPERVISOR_PORT_HB),
>> - "S" (in4),
>> - "D" (in5),
>> [in6] VMW_BP_CONSTRAINT (in6)
>> : "cc", "memory");
>> return out0;
>
Powered by blists - more mailing lists