DF-1315 / trigger_path.c
/* * DF-1315 trigger-path documentation (NOT runnable on this guest). * * The isolation break is in the NVMM AMD-SVM backend at * sys/dev/virtual/nvmm/x86/nvmm_x86_svm.c (svm_vcpu_guest_dbregs_enter/leave) * and sys/dev/virtual/nvmm/x86/nvmm_x86_internal.h (x86_curthread_*_dbregs). * * Trigger (requires an AMD host with SVM, nvmm available, and a VM run by a * user able to open /dev/nvmm): * 1. A guest under nvmm (AMD-SVM) executes MOV DR7 to arm a data breakpoint * (e.g. break-on-data-access) on a chosen address in DR0, with DR7 enabled * and intercept_dr clear so the write is not trapped. * 2. On #VMEXIT, AMD hardware does NOT restore host DR7 (no host-save-area * for debug regs). svm_vcpu_guest_dbregs_leave() calls * x86_curthread_restore_dbregs(), which early-returns when PCB_DBREGS is * unset (the common case), so the guest's DR7/DR0 remain armed. * 3. The host then takes a spurious #DB when it touches that address -> * host DoS / isolation break. * * The QEMU audit guest CPU has NO SVM feature bit * (AMD Features=0x20100800<SYSCALL,NX,LM>; SVM bit 0x1000 absent) and nvmm.ko * is not loaded, so the SVM backend cannot initialise here. * * Vulnerable signature: * nvmm_x86_internal.h:146 if (!(pcb->pcb_flags & PCB_DBREGS)) return; // save: no-op * nvmm_x86_internal.h:161 if (!(pcb->pcb_flags & PCB_DBREGS)) return; // restore: no-op, DR7 stays armed * nvmm_x86_svm.c:1510 x86_curthread_restore_dbregs(cpudata->hstate.drs); // guest DR7 persists * * fix.diff saves host DR7 unconditionally on enter and restores it * unconditionally on leave, so a guest-armed breakpoint cannot persist. */ int main(void) { return 0; } |