DF-2273 / verdict.json
{ "finding_id": "DF-2273", "status": "reproduced", "reproduced": 1, "impact": "none", "confidence": "certain", "verdict": "The unbounded strlen at scsi_ch.c:1300 reproduces exactly as claimed: with no NUL in the 33-byte cv_volid the scan ran 36 bytes, past the field through cv_serial and padding into adjacent bytes of the kernel stack copy (interposed counting shim, strlen_over33=1 strlen_max=36), while the retained ssvtp.vitf copy stayed bounded at 32 data bytes plus space padding (svt_vitf_nonspace=32) — a scan-only over-read with nothing retained. Containment established: DragonFlys ioctl layer copyins the csvr once into a kernel stack buffer (sys_generic.c:685 -> :724), so the walk cannot reach user memory or unmapped pages; the page-boundary/PROT_NONE experiment completed with no fault. The strnlen bound (fix.diff) caps the scan at 33 on the fixed kernel (strnlen_max=33, strlen_calls=0) with identical retained output. Info severity stands; no security impact beyond hardening.", "exploit_chain": "", "evidence": "voltag_baseline.log (strlen_over33=1 strlen_max=36 svt_vitf_nonspace=32), voltag_fixed.log (strnlen_calls=5 strnlen_max=33 strlen_calls=0), boundary lines in both logs (clean SUCCESS, no fault), rig df_post.c dfh_strlen/dfh_strnlen instrumentation", "kernel_refs": ["sys/bus/cam/scsi/scsi_ch.c:1300", "sys/bus/cam/scsi/scsi_ch.c:1301", "sys/sys/chio.h:133", "sys/bus/cam/scsi/scsi_ch.h:299", "sys/kern/sys_generic.c:685", "sys/kern/sys_generic.c:724"], "poc_changes": "No seed existed; wrote ch_user.c vt/boundary subcommands plus the dfh_strlen/dfh_strnlen counting interposition in the harness postamble.", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT x86_64 (baseline kernel #2 Sun Oct 18 00:11:42; fixed kernel #1 Sun Oct 18 00:24:51)", "runtime_sec": 300, "guest_dirty": 0, "build_cmd": "see ../DF-2270/rig/build.sh (shared harness kernel)", "run_cmd": "vm.sh run_root /root/ch_user vt 0|5|32|none|far|boundary; vm.sh run_root sysctl debug.dfch.stats", "code_hash": "0b7d48862ca46ac581c954486df7c4a0b9bef6ce7c409b371917ef0c61ccf4fa", "notes": "Scan stop at exactly 33 when the struct padding is zero (vt none/far use memset-0 structs); the 36-byte walk required a fully nonzero struct (boundary case). Adjacent bytes are kernel stack, not attacker content; nothing is disclosed.", "recommended_fix": "Bound the scan: replace strlen with strnlen(cv_volid, sizeof(cv_volid)) in the min() at scsi_ch.c:1300 (fix.diff)" } |