β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-1315

Guest debug registers (DR7/DR0-3) persist in host after #VMEXIT enabling host kernel panic via injected HW breakpoint

Summary

AMD SVM does NOT restore host DR7 on #VMEXIT (no host-save-area for DRs). VMRUN loads guest DR7 from VMCB, #VMEXIT leaves it active in hardware. svm_vcpu_guest_dbregs_leave() (:1500) calls x86_curthread_restore_dbregs() which early-returns without clearing DR7 when PCB_DBREGS is unset (common case, nvmm_x86_internal.h:161). Guest sets DR0=kernel_addr + DR7=data_breakpoint (intercept_dr=0 at :2257, no VMEXIT on mov dr). HLT -> VMEXIT -> host runs exit handlers with guest DR7 active -> kernel touches watched addr -> #DB in kernel mode -> trap_fatal() -> panic. VM ISOLATION BREAK. nvmm group only. Same bug in VMX backend. Fix: x86_set_dr7(0) after svm_vmrun and in dbregs_leave.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1315 Β· 9 files
FileTypeDescriptionSize
VERDICT.md verdict source-trace verdict: guest DR7 persists in host context (SVM has no host DR save area) 3.0 KB ↓ raw
README.md readme build/run/expected for this hardware-gated finding 2.0 KB ↓ raw
trigger_path.c trigger-source documents the unreachable trigger path (no SVM on guest CPU) 1.7 KB view raw
fix.diff suggested-fix save host DR7 unconditionally on enter, restore unconditionally on leave 847 B view raw
build.sh build-log no userspace PoC; documents hardware-gated nature 389 B view raw
run.sh run-log reachability check (module/PCI/CPU) 677 B view raw
env.txt environment guest uname, cc, PCI, CPU (no SVM), module presence 2.2 KB view raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme build/run/expected for this hardware-gated finding
↓ download raw

DF-1298 / DF-1305 / DF-1314 / DF-1315 β€” hardware-gated driver findings

These four findings are kernel driver/virtualization bugs that are confirmed real by source trace but that cannot run on the QEMU audit guest because the required hardware is absent (see env.txt):

Finding Subsystem Required hardware Present on guest?
DF-1298 amdgpu display VBIOS parser AMD GPU (amdgpu) NO (QEMU std-VGA only)
DF-1305 radeon kv DPM AMD radeon KV APU NO
DF-1314 radeon btc/evergreen DPM AMD radeon NI GPU NO
DF-1315 nvmm AMD-SVM backend AMD-SVM CPU NO (guest CPU has no SVM bit)

Build

./build.sh

There is no userspace PoC binary to compile for these β€” the vulnerable code is inside a kernel driver/VMM module that only executes when the relevant device attaches or the SVM backend runs. build.sh documents this.

Run

./run.sh

run.sh performs a reachability check (kldstat, pciconf, dmesg) and reports that the path is unreachable on this guest. No panic/leak is expected here because the trigger hardware is absent.

Expected (bug present, on a host WITH the hardware)

Each VERDICT.md describes the exact trigger and the kernel-level effect (heap overflow / OOB write / host DR7 persistence). On this guest those are latent.

Reproduce the FIX validation

The fix for each is fix.diff. To compile-validate a module fix: 1. scp fix.diff to the guest; cd /usr/src && patch -p1 < fix.diff 2. Build the relevant module, e.g. cd /usr/src && make -j6 MODULES_OVERRIDE=... or a full make -j6 nativekernel KERNCONF=X86_64_GENERIC (which also builds modules). 3. Confirm the module/object compiles with no errors (see fix_build.log).

Runtime fix-behaviour cannot be compared on this guest because the PoC paths are hardware-gated; the fix is therefore classified not_testable with a compile + source-trace validation.

VERDICT.md verdict source-trace verdict: guest DR7 persists in host context (SVM has no host DR save area)
↓ download raw

DF-1315 β€” AMD-SVM guest debug registers persist in host context (nvmm)

Verdict

NOT TESTABLE AT RUNTIME on this guest β€” confirmed real latent vulnerability in source.

Mechanism (confirmed by source trace)

sys/dev/virtual/nvmm/x86/nvmm_x86_svm.c is DragonFly's NVMM AMD-SVM backend.

AMD SVM does not save/restore host debug registers across VMRUN/#VMEXIT (there is no host-save-area field for DR0–DR7, unlike Intel VMX's VMCS host state). NVMM relies on software save/restore around the VMRUN:

  • svm_vcpu_guest_dbregs_enter() (line 1486):
  • calls x86_curthread_save_dbregs(cpudata->hstate.drs) β€” but the DragonFly version (nvmm_x86_internal.h:142) early-returns without saving when PCB_DBREGS is unset (the common case), so host DR7 is not captured;
  • then x86_set_dr7(0) and loads guest DR0–DR3 into hardware.
  • VMRUN runs the guest. With intercept_dr clear (no DR interception), the guest's MOV DR7 writes go straight to hardware DR7, and a guest can arm a data breakpoint on a host kernel address in DR0 + DR7.
  • svm_vcpu_guest_dbregs_leave() (line 1500):
  • saves guest DR0–DR3;
  • calls x86_curthread_restore_dbregs(cpudata->hstate.drs) β€” which again early-returns without touching DR7 when PCB_DBREGS is unset. So the guest-armed DR7 stays loaded after #VMEXIT, and DR0 still holds the guest's chosen address.

Net effect: a guest under nvmm (AMD-SVM) can leave a hardware data breakpoint armed on a host address that persists into the host's execution context, so the next host code touching that address takes an unexpected #DB β†’ host DoS (or worse, depending on host #DB handling). This is a host/guest isolation break.

Why it does not reproduce on this guest

  • The guest CPU reports no AMD-SVM feature: AMD Features=0x20100800<SYSCALL,NX,LM> β€” the SVM bit (0x1000) is absent. NVMM's SVM backend will not initialise (no usable SVM), so the VMRUN path cannot be exercised, even if nvmm.ko were loaded (it is not in GENERIC and not loaded).
  • nvmm is a pseudo-device listed only in LINT64, not in X86_64_GENERIC.

Severity / realistic ceiling

On an AMD host with SVM, with nvmm available and a VM run by a user able to open /dev/nvmm, a malicious guest can poison the host's debug registers and induce host-side #DB faults β€” a host DoS / isolation break (the finding's CVSS reflects AV:L/AC:L/PR:L/S:C/A:H). Requires SVM hardware + nvmm access (often root-only to load the module / create a VM).

Fix (see fix.diff)

  • In svm_vcpu_guest_dbregs_enter: unconditionally save the host DR7 into cpudata->hstate.drs[DR7] before clearing it (so it is available to restore on exit regardless of PCB_DBREGS).
  • In svm_vcpu_guest_dbregs_leave: unconditionally restore that host DR7 after the PCB-gated restore, so a guest-armed breakpoint cannot persist. This mirrors how the misc/FPU state is already handled. Compile-validated (nvmm module build); runtime not exercisable (no SVM on guest).

Fix verification

not_testable

compile+boot validated -Werror

nativekernel rc=0, boots #1 clean
↓ fix.diffDragonFly 6.5-DEVELOPMENT #1: Fri Jul 17 11:03:53 UTC 2026

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. NVMM SVM guest DR7 persists past #VMEXIT -> host #DB isolation break. No SVM on guest CPU. nvmm not in GENERIC.