{
  "finding_id": "DF-2270",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "Missing bounds check on the user-supplied cesr_element_type (scsi_ch.c:1066) reproduced in full on the verbatim-driver harness kernel: the range gate at :1077-1079 evaluates against out-of-bounds heap words past int sc_counts[4], so with chet>=7 landing on heap value 0x5a5a5a5a the real /dev/ch0 CHIOGSTATUS returned SUCCESS for 300 and 1000 elements of element types that do not exist, while in-range controls validate correctly; driving the same bypassed count to 65535 with a 0xffff desclen computes a ~4GiB size and the kmalloc(M_DEVBUF, M_INTWAIT) at :1129 wedged the whole guest (pagedaemon continuous-paging warnings on serial, ssh death, force-kill + reset). No privesc: /dev/ch0 is root:operator 0600 (scsi_ch.c:364-366) and chopen requires SYSCAP_RESTRICTEDROOT (scsi_ch.c:396), verified live; impact is a root-triggerable OOB-read-driven authorization bypass plus guest-killing DoS. The one-hunk sibling-idiom fix (return EINVAL for type > CHET_DT) makes ges 8/1000 fail with EINVAL, keeps in-range behavior identical, and defuses the identical direct-call hang trigger (returns instantly, RES ccbs=0).",
  "exploit_chain": "open /dev/ch0 (root only) -> ioctl CHIOGSTATUS with cesr_element_type=8 (no bounds check) -> gate reads sc_counts[8] OOB = adjacent heap word (canary 0x5a5a5a5a) -> count-validation bypass (base+count accepted for nonexistent type) -> READ ELEMENT STATUS issued with OOB sc_firsts[8] as element address -> desclen*count size math -> kmalloc(~4GiB, M_DEVBUF, M_INTWAIT) -> pagedaemon death spiral -> guest-killing DoS. No write primitive, no unpriv path: escalation closed.",
  "evidence": "run_all.log (ges matrix: type 8/1000 SUCCESS vs type 1 count 17 EINVAL), run_dmesg.log (DFH2270MAP OOB value table), hang_serial.log + hang_pagedaemon.log (watchdog fired + Continuous paging + guest death), hang_iteration1.txt (honest harness-artifact panic note), run_fixed_all.log (A/B: OOB types EINVAL, in-range SUCCESS), rig/ for the full harness and scripts",
  "kernel_refs": ["sys/bus/cam/scsi/scsi_ch.c:1066", "sys/bus/cam/scsi/scsi_ch.c:1077", "sys/bus/cam/scsi/scsi_ch.c:1079", "sys/bus/cam/scsi/scsi_ch.c:1100", "sys/bus/cam/scsi/scsi_ch.c:1137", "sys/bus/cam/scsi/scsi_ch.c:1120", "sys/bus/cam/scsi/scsi_ch.c:1129", "sys/bus/cam/scsi/scsi_ch.c:158", "sys/bus/cam/scsi/scsi_ch.c:159", "sys/bus/cam/scsi/scsi_ch.c:805", "sys/bus/cam/scsi/scsi_ch.c:364", "sys/bus/cam/scsi/scsi_ch.c:396"],
  "poc_changes": "No seed existed; built the CAM verbatim-interposition kernel harness from scratch per the established scsi_sa/scsi_cd scaffolding (sha256-gated verbatim scsi_ch.c compiled into the kernel, interposed xpt/cam_periph externals, fabricated canary-backed softc, real /dev/ch0 via the drivers own make_dev, fake MODE SENSE / READ ELEMENT STATUS transport, userland ioctl driver). Fixed two rig bugs found during bring-up: MODE SENSE shim length guard (64 -> 30) and the hang-test kthread missing cam_periph_lock (iteration-1 lockmgr panic, documented).",
  "attempts": 4,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #2 Sun Oct 18 00:11:42 UTC 2026 x86_64 (baseline hang kernel #2; fix kernel #1 Sun Oct 18 00:24:51)",
  "runtime_sec": 4200,
  "guest_dirty": 0,
  "build_cmd": "cd rig && ./build.sh (push df_pre.c/df_post.c, gen.sh concatenates verbatim scsi_ch.c, make -j6 nativekernel KERNCONF=X86_64_GENERIC, installkernel, reboot; cc -O2 -o ch_user ch_user.c -lpthread)",
  "run_cmd": "cd rig && ./run_tests.sh && ./run_hang.sh (destructive) ; after fix: ./make_fix.sh && ./build.sh && ./run_fixed.sh",
  "code_hash": "5eb5c8f0e7bf459728dca4e72adf418e0125b82fd877c44d1cb2a897c48bf60f",
  "notes": "OOB reads are heap-layout dependent: chet 4-5 read sc_movemask/sc_exchangemask bytes (0xffffffff, gate rejects), chet 6 reads settledelay+pad, chet>=7 read past-struct heap (canary, gate accepts). On a real changer the OOB sc_firsts value also lands in the SCSI CDB. Guest left clean (vm.sh reset with-src after the destructive run; final state: fixed harness kernel, source tree with fix227x_all.diff applied on the GUEST copy only).",
  "recommended_fix": "Add the sibling bounds-check idiom in chgetelemstatus: if (cesr->cesr_element_type > CHET_DT) return (EINVAL); before the sc_counts range check (fix.diff)"
}
