aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBojan Novković <bnovkov@FreeBSD.org>2024-09-29 11:10:10 +0000
committerBojan Novković <bnovkov@FreeBSD.org>2024-10-02 16:43:36 +0000
commit51fda658baa3f80c9778f3a9873fbf67df87119b (patch)
tree2dce91e4e17292f84cf39f6c06d26ad2fd5e6b08
parent26bd374e72681860af4bf9d639308ad245949460 (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.c10
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, &copyinfo, 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(&copyinfo, &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, &copyinfo, sizeof(uint64_t));
- vm_copy_teardown(&copyinfo, 1);
+ vm_copyout(&rflags, copyinfo, sizeof(uint64_t));
+ vm_copy_teardown(copyinfo, nitems(copyinfo));
return (0);
}