vmm: Improve register get/set handling a bit

On non-amd64 platforms, check for negative register indices.  This isn't
required today since we match against individual register indices, but
we might as well check it.  On amd64, add a comment explaining why we
permit negative register indices.

Use mallocarray() for allocating register arrays in the ioctl layer.

No functional change intended.

Reviewed by:	corvink
MFC after:	2 weeks
Sponsored by:	The FreeBSD Foundation
Sponsored by:	Klara, Inc.
Differential Revision:	https://reviews.freebsd.org/D53143
This commit is contained in:
Mark Johnston
2025-10-21 17:34:11 +00:00
parent 05637c8224
commit 14133abfe9
4 changed files with 14 additions and 15 deletions
+2 -1
View File
@@ -870,7 +870,7 @@ vm_assign_pptdev(struct vm *vm, int bus, int slot, int func)
int
vm_get_register(struct vcpu *vcpu, int reg, uint64_t *retval)
{
/* Negative values represent VM control structure fields. */
if (reg >= VM_REG_LAST)
return (EINVAL);
@@ -882,6 +882,7 @@ vm_set_register(struct vcpu *vcpu, int reg, uint64_t val)
{
int error;
/* Negative values represent VM control structure fields. */
if (reg >= VM_REG_LAST)
return (EINVAL);
+2 -3
View File
@@ -1279,8 +1279,7 @@ vcpu_get_state(struct vcpu *vcpu, int *hostcpu)
int
vm_get_register(struct vcpu *vcpu, int reg, uint64_t *retval)
{
if (reg >= VM_REG_LAST)
if (reg < 0 || reg >= VM_REG_LAST)
return (EINVAL);
return (vmmops_getreg(vcpu->cookie, reg, retval));
@@ -1291,7 +1290,7 @@ vm_set_register(struct vcpu *vcpu, int reg, uint64_t val)
{
int error;
if (reg >= VM_REG_LAST)
if (reg < 0 || reg >= VM_REG_LAST)
return (EINVAL);
error = vmmops_setreg(vcpu->cookie, reg, val);
if (error || reg != VM_REG_GUEST_PC)
+8 -8
View File
@@ -656,10 +656,10 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
error = EINVAL;
break;
}
regvals = malloc(sizeof(regvals[0]) * vmregset->count, M_VMMDEV,
M_WAITOK);
regnums = malloc(sizeof(regnums[0]) * vmregset->count, M_VMMDEV,
M_WAITOK);
regvals = mallocarray(vmregset->count, sizeof(regvals[0]),
M_VMMDEV, M_WAITOK);
regnums = mallocarray(vmregset->count, sizeof(regnums[0]),
M_VMMDEV, M_WAITOK);
error = copyin(vmregset->regnums, regnums, sizeof(regnums[0]) *
vmregset->count);
if (error == 0)
@@ -682,10 +682,10 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
error = EINVAL;
break;
}
regvals = malloc(sizeof(regvals[0]) * vmregset->count, M_VMMDEV,
M_WAITOK);
regnums = malloc(sizeof(regnums[0]) * vmregset->count, M_VMMDEV,
M_WAITOK);
regvals = mallocarray(vmregset->count, sizeof(regvals[0]),
M_VMMDEV, M_WAITOK);
regnums = mallocarray(vmregset->count, sizeof(regnums[0]),
M_VMMDEV, M_WAITOK);
error = copyin(vmregset->regnums, regnums, sizeof(regnums[0]) *
vmregset->count);
if (error == 0)
+2 -3
View File
@@ -954,8 +954,7 @@ vcpu_get_state(struct vcpu *vcpu, int *hostcpu)
int
vm_get_register(struct vcpu *vcpu, int reg, uint64_t *retval)
{
if (reg >= VM_REG_LAST)
if (reg < 0 || reg >= VM_REG_LAST)
return (EINVAL);
return (vmmops_getreg(vcpu->cookie, reg, retval));
@@ -966,7 +965,7 @@ vm_set_register(struct vcpu *vcpu, int reg, uint64_t val)
{
int error;
if (reg >= VM_REG_LAST)
if (reg < 0 || reg >= VM_REG_LAST)
return (EINVAL);
error = vmmops_setreg(vcpu->cookie, reg, val);
if (error || reg != VM_REG_GUEST_SEPC)