untrusted comment: verify with openbsd-66-base.pub
RWSvK/c+cFe24AxipdqCUWAjUtIAO0sKPUESnkKS/ap3EnoVDEVbk8Oq8ym/c/M423lIak4AQbJOHeJaMaDAfzhQM7ns06BHNww=
OpenBSD 6.6 errata 020, February 17, 2020:
A missing range check in the vmm pvclock allows a guest to write
to host memory.
Apply by doing:
signify -Vep /etc/signify/openbsd-66-base.pub -x 020_vmm_pvclock.patch.sig \
-m - | (cd /usr/src && patch -p0)
And then rebuild and install a new kernel:
KK=`sysctl -n kern.osversion | cut -d# -f1`
cd /usr/src/sys/arch/`machine`/compile/$KK
make obj
make config
make
make install
Index: sys/arch/amd64/amd64/vmm.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/vmm.c,v
retrieving revision 1.254
diff -u -p -u -r1.254 vmm.c
--- sys/arch/amd64/amd64/vmm.c 22 Sep 2019 08:47:54 -0000 1.254
+++ sys/arch/amd64/amd64/vmm.c 15 Feb 2020 23:26:47 -0000
@@ -202,6 +202,7 @@ void vmx_setmsrbrw(struct vcpu *, uint32
void svm_set_clean(struct vcpu *, uint32_t);
void svm_set_dirty(struct vcpu *, uint32_t);
+int vmm_gpa_is_valid(struct vcpu *vcpu, paddr_t gpa, size_t obj_size);
void vmm_init_pvclock(struct vcpu *, paddr_t);
int vmm_update_pvclock(struct vcpu *);
@@ -6875,9 +6876,45 @@ vmm_free_vpid(uint16_t vpid)
rw_exit_write(&vmm_softc->vpid_lock);
}
+
+/* vmm_gpa_is_valid
+ *
+ * Check if the given gpa is within guest memory space.
+ *
+ * Parameters:
+ * vcpu: The virtual cpu we are running on.
+ * gpa: The address to check.
+ * obj_size: The size of the object assigned to gpa
+ *
+ * Return values:
+ * 1: gpa is within the memory ranges allocated for the vcpu
+ * 0: otherwise
+ */
+int
+vmm_gpa_is_valid(struct vcpu *vcpu, paddr_t gpa, size_t obj_size)
+{
+ struct vm *vm = vcpu->vc_parent;
+ struct vm_mem_range *vmr;
+ for (size_t i = 0; i < vm->vm_nmemranges; ++i) {
+ vmr = &vm->vm_memranges[i];
+ if (vmr->vmr_gpa <= gpa &&
+ gpa < (vmr->vmr_gpa + vmr->vmr_size - obj_size)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
void
vmm_init_pvclock(struct vcpu *vcpu, paddr_t gpa)
{
+ if (!vmm_gpa_is_valid(vcpu, gpa & 0xFFFFFFFFFFFFFFF0,
+ sizeof(struct pvclock_time_info))) {
+ /* XXX: Kill guest? */
+ vmm_inject_gp(vcpu);
+ return;
+ }
+
vcpu->vc_pvclock_system_gpa = gpa;
vcpu->vc_pvclock_system_tsc_mul =
(int) ((1000000000L << 20) / tc_getfrequency());