lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <uc62gsttzmh5o35uh7viy326bqwpq5gxmcxqqyqb4zp4blp7tg@v3kfsotqtaay>
Date: Fri, 6 Feb 2026 08:32:51 -0800
From: Josh Poimboeuf <jpoimboe@...nel.org>
To: Thomas Gleixner <tglx@...-um.de>
Cc: Thorsten Leemhuis <regressions@...mhuis.info>, 
	Alexey Makhalov <alexey.makhalov@...adcom.com>, x86@...nel.org, 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>, Linus Torvalds <torvalds@...ux-foundation.org>
Subject: Re: [PATCH] x86/vmware: Fix hypercall clobbers

On Fri, Feb 06, 2026 at 11:07:22AM +0100, Thomas Gleixner wrote:
> So unless there is a compelling argument why the existing hypercall
> implementation is broken by design, the trivial one-line fix from Alexey
> is addressing the actual root cause (it just needs a big fat comment)
> and good enough to cure the regression, no?

While my original patch might be overkill, Alexey's one-line fix doesn't
go far enough:

  1) It only changes one hypercall site, the vmmouse driver has several.
     All of the following commands are subject to register corruption by
     QEMU:

       VMWARE_CMD_ABSPOINTER_DATA
       VMWARE_CMD_ABSPOINTER_STATUS
       VMWARE_CMD_ABSPOINTER_COMMAND
     
  2) While the inline asm for vmware_hypercall7() does have RSI/RDI
     listed as input constraints, it doesn't clobber them.

So a spot fix would need to be something like so:

diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h
index c9cf43d5ef23..9f72569fc8c2 100644
--- a/arch/x86/include/asm/vmware.h
+++ b/arch/x86/include/asm/vmware.h
@@ -119,6 +119,27 @@ unsigned long vmware_hypercall1(unsigned long cmd, unsigned long in1)
 	return out0;
 }
 
+static inline
+unsigned long vmware_hypercall1_clobber(unsigned long cmd, unsigned long in1)
+{
+	unsigned long out0, tmp = 0;
+
+	if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+		return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
+					    NULL, NULL, NULL, NULL, NULL);
+
+	if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
+		return vmware_hypercall_slow(cmd, in1, 0, 0, 0,
+					     NULL, NULL, NULL, NULL, NULL);
+
+	asm_inline volatile (VMWARE_HYPERCALL
+		: "=a" (out0), "+b" (in1), "+c" (cmd), "+d" (tmp)
+		: [port] "i" (VMWARE_HYPERVISOR_PORT),
+		  "a" (VMWARE_HYPERVISOR_MAGIC)
+		: "di", "si", "cc", "memory");
+	return out0;
+}
+
 static inline
 unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
 				u32 *out1, u32 *out2)
@@ -144,6 +165,30 @@ unsigned long vmware_hypercall3(unsigned long cmd, unsigned long in1,
 	return out0;
 }
 
+static inline
+unsigned long vmware_hypercall3_clobber(unsigned long cmd, unsigned long in1,
+					u32 *out1, u32 *out2)
+{
+	unsigned long out0, tmp = 0;
+
+	if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+		return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
+					    out1, out2, NULL, NULL, NULL);
+
+	if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
+		return vmware_hypercall_slow(cmd, in1, 0, 0, 0,
+					     out1, out2, NULL, NULL, NULL);
+
+	asm_inline volatile (VMWARE_HYPERCALL
+		: "=a" (out0), "=b" (*out1), "=c" (*out2), "+d" (tmp)
+		: [port] "i" (VMWARE_HYPERVISOR_PORT),
+		  "a" (VMWARE_HYPERVISOR_MAGIC),
+		  "b" (in1),
+		  "c" (cmd)
+		: "di", "si", "cc", "memory");
+	return out0;
+}
+
 static inline
 unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1,
 				u32 *out1, u32 *out2, u32 *out3)
@@ -169,6 +214,31 @@ unsigned long vmware_hypercall4(unsigned long cmd, unsigned long in1,
 	return out0;
 }
 
+static inline
+unsigned long vmware_hypercall4_clobber(unsigned long cmd, unsigned long in1,
+					u32 *out1, u32 *out2, u32 *out3)
+{
+	unsigned long out0;
+
+	if (cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+		return vmware_tdx_hypercall(cmd, in1, 0, 0, 0,
+					    out1, out2, out3, NULL, NULL);
+
+	if (unlikely(!alternatives_patched) && !__is_defined(MODULE))
+		return vmware_hypercall_slow(cmd, in1, 0, 0, 0,
+					     out1, out2, out3, NULL, NULL);
+
+	asm_inline volatile (VMWARE_HYPERCALL
+		: "=a" (out0), "=b" (*out1), "=c" (*out2), "=d" (*out3)
+		: [port] "i" (VMWARE_HYPERVISOR_PORT),
+		  "a" (VMWARE_HYPERVISOR_MAGIC),
+		  "b" (in1),
+		  "c" (cmd),
+		  "d" (0)
+		: "di", "si", "cc", "memory");
+	return out0;
+}
+
 static inline
 unsigned long vmware_hypercall5(unsigned long cmd, unsigned long in1,
 				unsigned long in3, unsigned long in4,
diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c
index fb1d986a6895..0ab04b8bb923 100644
--- a/drivers/input/mouse/vmmouse.c
+++ b/drivers/input/mouse/vmmouse.c
@@ -125,7 +125,7 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse)
 
 	while (count--) {
 		/* See if we have motion data. */
-		status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0);
+		status = vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_STATUS, 0);
 		if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) {
 			psmouse_err(psmouse, "failed to fetch status data\n");
 			/*
@@ -145,8 +145,8 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse)
 		}
 
 		/* Now get it */
-		status = vmware_hypercall4(VMWARE_CMD_ABSPOINTER_DATA, 4,
-					   &x, &y, &z);
+		status = vmware_hypercall4_clobber(VMWARE_CMD_ABSPOINTER_DATA, 4,
+						   &x, &y, &z);
 
 		/*
 		 * And report what we've got. Prefer to report button
@@ -222,9 +222,9 @@ static void vmmouse_disable(struct psmouse *psmouse)
 {
 	u32 status;
 
-	vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE);
+	vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE);
 
-	status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0);
+	status = vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_STATUS, 0);
 	if ((status & VMMOUSE_ERROR) != VMMOUSE_ERROR)
 		psmouse_warn(psmouse, "failed to disable vmmouse device\n");
 }
@@ -246,19 +246,19 @@ static int vmmouse_enable(struct psmouse *psmouse)
 	 * Try enabling the device. If successful, we should be able to
 	 * read valid version ID back from it.
 	 */
-	vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE);
+	vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE);
 
 	/*
 	 * See if version ID can be retrieved.
 	 */
-	status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0);
+	status = vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_STATUS, 0);
 	if ((status & 0x0000ffff) == 0) {
 		psmouse_dbg(psmouse, "empty flags - assuming no device\n");
 		return -ENXIO;
 	}
 
-	version = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_DATA,
-				    1 /* single item */);
+	version = vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_DATA,
+					    1 /* single item */);
 	if (version != VMMOUSE_VERSION_ID) {
 		psmouse_dbg(psmouse, "Unexpected version value: %u vs %u\n",
 			    (unsigned) version, VMMOUSE_VERSION_ID);
@@ -269,11 +269,10 @@ static int vmmouse_enable(struct psmouse *psmouse)
 	/*
 	 * Restrict ioport access, if possible.
 	 */
-	vmware_hypercall1(VMWARE_CMD_ABSPOINTER_RESTRICT,
-			  VMMOUSE_RESTRICT_CPL0);
+	vmware_hypercall1(VMWARE_CMD_ABSPOINTER_RESTRICT, VMMOUSE_RESTRICT_CPL0);
 
-	vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND,
-			  VMMOUSE_CMD_REQUEST_ABSOLUTE);
+	vmware_hypercall1_clobber(VMWARE_CMD_ABSPOINTER_COMMAND,
+				  VMMOUSE_CMD_REQUEST_ABSOLUTE);
 
 	return 0;
 }
@@ -320,7 +319,7 @@ int vmmouse_detect(struct psmouse *psmouse, bool set_properties)
 
 	/* Check if the device is present */
 	response = ~VMWARE_HYPERVISOR_MAGIC;
-	version = vmware_hypercall3(VMWARE_CMD_GETVERSION, 0, &response, &type);
+	version = vmware_hypercall3_clobber(VMWARE_CMD_GETVERSION, 0, &response, &type);
 	if (response != VMWARE_HYPERVISOR_MAGIC || version == 0xffffffffU)
 		return -ENXIO;
 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ