git: ce5b70657f94 - main - vmm: Fix a page wiring leak in MOVS emulation

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 21 Sep 2026 16:41:25 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=ce5b70657f94d2051566664d3ea7167d104803b0

commit ce5b70657f94d2051566664d3ea7167d104803b0
Author:     Hayzam Sherif <hayzam@gmail.com>
AuthorDate: 2026-09-21 16:34:08 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-09-21 16:36:11 +0000

    vmm: Fix a page wiring leak in MOVS emulation
    
    When emulating a MOVS from MMIO to guest RAM, the kernel's
    vm_copy_setup() wires the destination pages.  If the subsequent
    MMIO read fails, emulate_movs() skips vm_copy_teardown(), leaking
    the page wire references acquired during setup.
    
    Run vm_copy_teardown() regardless of the MMIO read result, and
    only copy the value to guest memory if the read succeeds.
    Preserve the existing error return.
    
    This matches illumos change 13309.
    
    Reviewed by:    markj
    Obtained from:  illumos 83cd75bb2949d26e6eb38ddefc60fdeed1909643
    MFC after:      2 weeks
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D59823
---
 sys/amd64/vmm/vmm_instruction_emul.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/sys/amd64/vmm/vmm_instruction_emul.c b/sys/amd64/vmm/vmm_instruction_emul.c
index c54b6e6d0074..963da132c36b 100644
--- a/sys/amd64/vmm/vmm_instruction_emul.c
+++ b/sys/amd64/vmm/vmm_instruction_emul.c
@@ -858,11 +858,17 @@ emulate_movs(struct vcpu *vcpu, uint64_t gpa, struct vie *vie,
 			 * before the MMIO read is attempted.
 			 */
 			error = memread(vcpu, gpa, &val, opsize, arg);
-			if (error)
-				goto done;
+			if (error == 0)
+				vm_copyout(&val, copyinfo, opsize);
 
-			vm_copyout(&val, copyinfo, opsize);
+			/*
+			 * Release the copy resources even if the MMIO read
+			 * failed.
+			 */
 			vm_copy_teardown(copyinfo, nitems(copyinfo));
+
+			if (error != 0)
+				goto done;
 		} else {
 			/*
 			 * Case (4): read from and write to mmio.