untrusted comment: verify with openbsd-73-base.pub
RWQS90bYzZ4XFl/L1sXKI9Jm30jpG5J+42sawcM1OsKQO0A6b+LLS4wOuol4oxTLff7S4it3U8xs8bA7AMSuiCYOHA5N5LgmRwA=
OpenBSD 7.3 errata 022, December 10, 2023:
vmm(4) restored stale GDTR & TR values on vm exit which could lead to
memory corruption or kernel deadlocks.
Apply by doing:
signify -Vep /etc/signify/openbsd-73-base.pub -x 022_vmm.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/Attic/vmm.c,v
diff -u -p -r1.337 vmm.c
--- sys/arch/amd64/amd64/vmm.c 30 Jan 2023 14:05:36 -0000 1.337
+++ sys/arch/amd64/amd64/vmm.c 27 Nov 2023 16:39:06 -0000
@@ -4821,7 +4821,7 @@ vcpu_run_vmx(struct vcpu *vcpu, struct v
{
int ret = 0, exitinfo;
struct region_descriptor gdt;
- struct cpu_info *ci = curcpu();
+ struct cpu_info *ci = NULL;
uint64_t exit_reason, cr3, insn_error;
struct schedstate_percpu *spc;
struct vmx_invvpid_descriptor vid;
@@ -4900,26 +4900,6 @@ vcpu_run_vmx(struct vcpu *vcpu, struct v
memset(&vcpu->vc_exit, 0, sizeof(vcpu->vc_exit));
}
- setregion(&gdt, ci->ci_gdt, GDT_SIZE - 1);
- if (gdt.rd_base == 0) {
- printf("%s: setregion\n", __func__);
- return (EINVAL);
- }
-
- /* Host GDTR base */
- if (vmwrite(VMCS_HOST_IA32_GDTR_BASE, gdt.rd_base)) {
- printf("%s: vmwrite(0x%04X, 0x%llx)\n", __func__,
- VMCS_HOST_IA32_GDTR_BASE, gdt.rd_base);
- return (EINVAL);
- }
-
- /* Host TR base */
- if (vmwrite(VMCS_HOST_IA32_TR_BASE, (uint64_t)ci->ci_tss)) {
- printf("%s: vmwrite(0x%04X, 0x%llx)\n", __func__,
- VMCS_HOST_IA32_TR_BASE, (uint64_t)ci->ci_tss);
- return (EINVAL);
- }
-
/* Host CR3 */
cr3 = rcr3();
if (vmwrite(VMCS_HOST_IA32_CR3, cr3)) {
@@ -4976,6 +4956,34 @@ vcpu_run_vmx(struct vcpu *vcpu, struct v
#endif /* VMM_DEBUG */
vmm_update_pvclock(vcpu);
+
+ if (ci != curcpu()) {
+ ci = curcpu();
+ vcpu->vc_last_pcpu = ci;
+
+ setregion(&gdt, ci->ci_gdt, GDT_SIZE - 1);
+ if (gdt.rd_base == 0) {
+ printf("%s: setregion\n", __func__);
+ return (EINVAL);
+ }
+
+ /* Host GDTR base */
+ if (vmwrite(VMCS_HOST_IA32_GDTR_BASE, gdt.rd_base)) {
+ printf("%s: vmwrite(0x%04X, 0x%llx)\n",
+ __func__, VMCS_HOST_IA32_GDTR_BASE,
+ gdt.rd_base);
+ return (EINVAL);
+ }
+
+ /* Host TR base */
+ if (vmwrite(VMCS_HOST_IA32_TR_BASE,
+ (uint64_t)ci->ci_tss)) {
+ printf("%s: vmwrite(0x%04X, 0x%llx)\n",
+ __func__, VMCS_HOST_IA32_TR_BASE,
+ (uint64_t)ci->ci_tss);
+ return (EINVAL);
+ }
+ }
/* Inject event if present */
if (vcpu->vc_event != 0) {