diff options
| author | Bojan Novković <bnovkov@FreeBSD.org> | 2024-09-29 11:10:10 +0000 |
|---|---|---|
| committer | Bojan Novković <bnovkov@FreeBSD.org> | 2024-10-02 16:43:36 +0000 |
| commit | 51fda658baa3f80c9778f3a9873fbf67df87119b (patch) | |
| tree | 2dce91e4e17292f84cf39f6c06d26ad2fd5e6b08 | |
| parent | 26bd374e72681860af4bf9d639308ad245949460 (diff) | |
vmm: Properly handle writes spanning across two pages in vm_handle_db
The vm_handle_db function is responsible for writing correct status
register values into memory when a guest VM is being single-stepped
using the RFLAGS.TF mechanism. However, it currently does not properly
handle an edge case where the resulting write spans across two pages.
This commit fixes this by making vm_handle_db use two vm_copy_info
structs.
Security: HYP-09
Reviewed by: markj
| -rw-r--r-- | sys/amd64/vmm/vmm.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index a2c2b342bee4..5484d71cefd2 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -1795,7 +1795,7 @@ vm_handle_db(struct vcpu *vcpu, struct vm_exit *vme, bool *retu) int error, fault; uint64_t rsp; uint64_t rflags; - struct vm_copyinfo copyinfo; + struct vm_copyinfo copyinfo[2]; *retu = true; if (!vme->u.dbg.pushf_intercept || vme->u.dbg.tf_shadow_val != 0) { @@ -1804,21 +1804,21 @@ vm_handle_db(struct vcpu *vcpu, struct vm_exit *vme, bool *retu) vm_get_register(vcpu, VM_REG_GUEST_RSP, &rsp); error = vm_copy_setup(vcpu, &vme->u.dbg.paging, rsp, sizeof(uint64_t), - VM_PROT_RW, ©info, 1, &fault); + VM_PROT_RW, copyinfo, nitems(copyinfo), &fault); if (error != 0 || fault != 0) { *retu = false; return (EINVAL); } /* Read pushed rflags value from top of stack. */ - vm_copyin(©info, &rflags, sizeof(uint64_t)); + vm_copyin(copyinfo, &rflags, sizeof(uint64_t)); /* Clear TF bit. */ rflags &= ~(PSL_T); /* Write updated value back to memory. */ - vm_copyout(&rflags, ©info, sizeof(uint64_t)); - vm_copy_teardown(©info, 1); + vm_copyout(&rflags, copyinfo, sizeof(uint64_t)); + vm_copy_teardown(copyinfo, nitems(copyinfo)); return (0); } |
