DF-5123 / verdict.json
{ "finding_id": "DF-5123", "status": "not_reproduced", "reproduced": false, "impact": "none", "confidence": "likely", "verdict": "The inline-asm contract violation in hypercall_md() (hyperv_machdep.c:74-84) is certain by inspection and structurally confirmed by codegen evidence: compiling an exact copy of the function with the guests gcc 8.3 at -O2 shows the compiler emitting an operand-setup instruction (mov %rsi,%rcx) BETWEEN the two asm statements - i.e. the gap in which %r8 must survive is not compiler-free, and the first asm declares r8 clobbered, so nothing prevents a future allocation from destroying out_paddr before the indirect call. The indirect-call asm also lacks r9-r11/rsi/rdi/cc clobbers and a memory clobber (hypercalls read/write their in/out pages). However, with the shipping compiler (gcc 8.3, -O2, no LTO) the standalone function and an always_inline variant both keep r8 intact, and the guest is KVM so the Hyper-V code is dormant - no miscompile manifests: hence not_reproduced / latent. Impact if it ever manifests: hypercalls invoked with a corrupted output-page GFN or stale message-page contents.", "exploit_chain": "", "evidence": "objdump_gcc83_O2.txt / build.log: disassembly of hypercall_md showing mov %rsi,%rcx emitted between mov %rcx,%r8 (asm 1) and callq *-0x8(%rsp) (asm 2) - proof the inter-asm gap carries compiler code while r8s lifetime is undeclared; VERDICT.md walks the analysis; env.txt documents guest compiler (cc 8.3 DragonFly) and KVM (dormant path)", "kernel_refs": [ "sys/dev/virtual/hyperv/x86_64/hyperv_machdep.c:74-84", "sys/dev/virtual/hyperv/hyperv.c:105-110", "sys/dev/virtual/hyperv/vmbus/vmbus.c:366" ], "poc_changes": "Seed sketch replaced entirely: the PoC is a codegen demonstration (exact function copy + always_inline variant) compiled on the guest, not a runtime trigger - a runtime hypercall PoC is impossible on a KVM guest.", "attempts": 1, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026\troot@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC\t x86_64", "runtime_sec": 12, "guest_dirty": 0, "build_cmd": "sh findings/poc/DF-5123/build.sh (ssh to guest: cc -O2 -c hypercall_md.c && objdump -d)", "run_cmd": "sh findings/poc/DF-5123/run.sh (structural check of the disassembly)", "code_hash": "2024f3d4a6acd3c67e9f984b0eef0888b2bacdfe079bb93e04513bd1d73a88e6", "notes": "Info-class hardening finding; the defect (contract violation) is certain, the consequence (miscompile) is latent - gcc 8.3 happens to keep r8 alive across the gap today. fix.diff merges the two asms into one with the full clobber list (r8,r9,r10,r11,memory,cc).", "recommended_fix": "Single asm: __asm__ __volatile__(\"movq %3, %%r8\\n\\tcall *%4\" : \"=a\"(status) : \"c\"(in_val), \"d\"(in_paddr), \"r\"(out_paddr), \"m\"(hc_addr) : \"r8\",\"r9\",\"r10\",\"r11\",\"memory\",\"cc\");", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Fix not built into a kernel: the miscompile does not manifest on the shipping compiler and the path is dormant on the KVM guest, so no baseline/patched runtime comparison exists; the corrected asm is mechanically equivalent to the current codegen (verified shape in objdump) minus the contract violations.", "fix_evidence": "findings/poc/DF-5123/fix.diff" } |