DF-4987 / verdict.json
{ "finding_id": "DF-4987", "status": "not_reproduced", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Hardware-gated: the audit guest has no LSI 3ware controller, so /dev/tws0 does not exist and the ioctl cannot be issued (PoC builds clean and exits ENOENT, run.log). The defect itself is unconditional control flow: tws_user.c:117 assigns the raw u32 driver_pkt.buffer_length to req->length with no bound; tws_user.c:120 kmallocs that size (up to ~4 GiB, M_WAITOK|M_ZERO); the copyin error at tws_user.c:121 is ignored and the command still executes; bus_dmamap_load (maxsize 128 kB / 46 segs, tws.c:518-533) delivers EFBIG which tws_cam.c:1019-1048 only traces before SUBMITTING the command with a truncated SGL; bounce-needing buffers (>4 GB physical backing) hit reserve_bounce_pages shortfall -> EINPROGRESS -> panic(protected dmamap callback will be defered) at busdma_machdep.c:793-799 (KKASSERT above it fires first on INVARIANTS kernels); and any non-completing command sleeps 60 s uninterruptibly (no PCATCH) then triggers a controller-wide tws_reset. Expected impact on hardware: root-gated storage-stack DoS + kernel-memory exhaustion + certain kernel panic on >4 GB RAM hosts.", "exploit_chain": "", "evidence": "run.log (clean build + ENOENT + pciconf showing no LSI RAID device); VERDICT.md (6-step code trace with path:line); tws_pt_len.c (self-contained struct mirrors of tws_hdm.h/tws_user.h, constructs the oversized passthru command)", "kernel_refs": [ "sys/dev/raid/tws/tws_user.c:117-122", "sys/dev/raid/tws/tws_user.c:139-147", "sys/dev/raid/tws/tws_cam.c:989-1004", "sys/dev/raid/tws/tws_cam.c:1019-1048", "sys/dev/raid/tws/tws.c:518-533", "sys/platform/pc64/x86_64/busdma_machdep.c:644-657", "sys/platform/pc64/x86_64/busdma_machdep.c:793-799" ], "poc_changes": "n/a (authored fresh); struct layouts mirrored from tws_hdm.h/tws_user.h into the PoC so it builds against stock guest headers", "attempts": 1, "guest_uname": "DragonFly dfbsd 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": 25, "guest_dirty": 0, "build_cmd": "cc -O2 -Wall -o tws_pt_len tws_pt_len.c", "run_cmd": "./tws_pt_len 0x7fff0000", "code_hash": "2987207f961d3230ad227a56f81517741efb05e5f424d86dca24d7973f1f3c6c", "notes": "Guest has 4 GB RAM (all physical < 4 GB), so the bounce-page/panic sub-path is unreachable on this guest even with hardware \u2014 noted, not a code uncertainty. Root-only 0600 device node (tws.c:284-286) gates the trigger; rated Medium for array-wide reset + certain panic path on >4 GB hosts.", "recommended_fix": "In tws_passthru, reject driver_pkt.buffer_length > TWS_MAX_IO_SIZE with EINVAL before allocation and abort with request release when copyin fails instead of submitting the command with zeroed data", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "Hardware-gated (no 3ware controller on the guest); fix.diff adds the up-front length bound and the copyin-failure abort; the bound makes the oversized kmalloc, the EFBIG-truncated-SGL submission, and the protected-dmamap EINPROGRESS panic unreachable by construction." } |