DF-5172 / verdict.json
{ "finding_id": "DF-5172", "status": "not_reproduced", "reproduced": false, "impact": "none", "confidence": "likely", "verdict": "vcdstrategy() manipulates sc->bio_queue (bioqdisksort/bioq_takefirst, vcd.c:148-149) with zero serialization and holds the queue open across a blocking pread/pwrite - the same shape vdisks 2016 cothread rework fixed for vkd. NOT reproducible today because vcd_ops lacks D_MPSAFE (vcd.c:67), so dev_dstrategy() executes every strategy call under the global mplock (kern_device.c:119-121, 384-388): concurrent entries are impossible. Attempted on a 4-vCPU vkernel with 4x20000 mixed aligned reads/writes on /dev/vcd0 - clean survival, as the shield predicts. Filed as a latent hazard (Info): the day vcd is marked D_MPSAFE the race goes live with a window spanning a full host-side I/O syscall.", "exploit_chain": "", "evidence": "run.2.log:37-39 (DF-5172 vcd bioq race attempt, mixed r/w: reopening O_RDWR, RACE SURVIVED - no crash this run, clean init exit on 4 CPUs); run.log (read-only variant); run.s2-failed.log (documents that -s is RB_SINGLE, not ncpus - ncpus is -n, default boots 2 vCPUs); shield trace: vcd.c:67 + kern_device.c:119-121,384-388; sibling divergence: vdisk.c:228-231,250-255,279-298 (cothread_lock around all queue ops).", "kernel_refs": [ "sys/dev/virtual/vkernel/cdrom/vcd.c:148", "sys/dev/virtual/vkernel/cdrom/vcd.c:149", "sys/dev/virtual/vkernel/cdrom/vcd.c:67", "sys/kern/kern_device.c:119", "sys/kern/kern_device.c:384", "sys/kern/subr_disk.c:1353", "sys/sys/buf2.h:167", "sys/dev/virtual/vkernel/disk/vdisk.c:228" ], "poc_changes": "Wrote a static PID1 binary (vcd_race_poc.c) that opens /dev/vcd0 and forks 4 children doing 20000 lseek+read (second variant: 50/50 read/write via O_RDWR) each, logging to /dev/console (init stdio is dead in the vkernel). Two lessons baked in: offsets must be 2048-aligned (vcd media sector size) or dscheck silently rejects every bio before the driver sees them; -s is RB_SINGLE not ncpus (ncpus flag is -n; default vkernel boots 2 vCPUs).", "attempts": 3, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 600, "guest_dirty": 1, "build_cmd": "cc -static -O2 -o race src/vcd_race_poc.c (inside guest; harness per DF-5171 build.sh)", "run_cmd": "cd /root/vk && cp root.pristine root.img && timeout 120 ./vkernel64 -m 256M -n 4 -r root.img -c hammer.img -e init_path=/race < /dev/null > run.log 2>&1", "code_hash": "b0f6af29e6797122a43ae6263d438cd8ea86d9f68e9e7f38d83419344b2f14b4", "notes": "Latent race shielded by the missing D_MPSAFE flag (mplock serializes dev_dstrategy) - same external-guard shape as DF-5010s dscheck shield. Filed Info. Any future D_MPSAFE conversion of vcd must first adopt vkds cothread or an internal lock. No fix.diff: nothing observable to validate while the shield holds.", "recommended_fix": "Adopt vdisks cothread structure for vcd (or minimally guard bioqdisksort/bioq_takefirst and the drain loop with a lock/crit section) before ever marking vcd_ops D_MPSAFE." } |