git: f8db6fb90e73 - stable/14 - vmm: avoid potential KASSERT kernel panic in vm_handle_db

From: Ed Maste <emaste_at_FreeBSD.org>
Date: Sun, 06 Oct 2024 15:01:46 UTC
The branch stable/14 has been updated by emaste:

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

commit f8db6fb90e739293d6d72310fa554ede072f8232
Author:     Pierre Pronchery <pierre@freebsdfoundation.org>
AuthorDate: 2024-07-25 14:40:35 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2024-10-06 15:01:24 +0000

    vmm: avoid potential KASSERT kernel panic in vm_handle_db
    
    If the guest VM emits the exit code VM_EXITCODE_DB the kernel will
    execute the function named vm_handle_db.
    
    If the value of rsp is not page aligned and if rsp+sizeof(uint64_t)
    spans across two pages, the function vm_copy_setup will need two structs
    vm_copyinfo to prepare the copy operation.
    
    For instance is rsp value is 0xFFC, two vm_copyinfo objects are needed:
    
    * address=0xFFC, len=4
    * address=0x1000, len=4
    
    The vulnerability was addressed by commit 51fda658baa ("vmm: Properly
    handle writes spanning across two pages in vm_handle_db").  Still,
    replace the KASSERT with an error return as a more defensive approach.
    
    Reported by:    Synacktiv
    Reviewed by     markj, emaste
    Security:       HYP-09
    Sponsored by:   The Alpha-Omega Project
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D46133
    
    (cherry picked from commit d19fa9c1b72bc52e51524abcc59ad844012ec365)
---
 sys/amd64/vmm/vmm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index ef4c7a9af2ea..677dcd05b9b2 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -2786,7 +2786,8 @@ vm_copy_setup(struct vcpu *vcpu, struct vm_guest_paging *paging,
 	nused = 0;
 	remaining = len;
 	while (remaining > 0) {
-		KASSERT(nused < num_copyinfo, ("insufficient vm_copyinfo"));
+		if (nused >= num_copyinfo)
+			return (EFAULT);
 		error = vm_gla2gpa(vcpu, paging, gla, prot, &gpa, fault);
 		if (error || *fault)
 			return (error);