DF-4399 / verdict.json
{ "finding_id": "DF-4399", "status": "inconclusive", "reproduced": 0, "impact": "panic", "confidence": "certain", "verdict": "Code-level proof: the passthrough ioctl copies the users command packet verbatim (tws_user.c:126-127) including pkt_g.generic.size (u_int8_t, tws_hdm.h:275); tws_dmamap_data_load_cbfn (tws_cam.c:1034-1038) uses that byte as the u32-unit offset for the SGL write, so size=255 puts 16-byte DMA descriptors at cmd_buf[2]+1148 = offset 124 of cmd_buf[3]s packet \u2014 precisely its header_desc (size_header/request_id/size_sense) and command body \u2014 corrupting unrelated in-flight kernel command state. The DMA tag caps segment COUNT (46/93, tws.c:518-530) but not the offset. Root-only (/dev/tws0 is 0600, tws.c:284-286). Guest has no 3ware HBA, so not exercisable there.", "exploit_chain": "", "evidence": "VERDICT.md proof chain; trigger.c (real _IOWR(T,202) ioctl, size=255, SET_PARAM opcode); fix.diff (sink-side clamp); env.txt", "kernel_refs": [ "sys/dev/raid/tws/tws_cam.c:1030", "sys/dev/raid/tws/tws_cam.c:1035", "sys/dev/raid/tws/tws_user.c:117", "sys/dev/raid/tws/tws_user.c:126", "sys/dev/raid/tws/tws_hdm.h:275", "sys/dev/raid/tws/tws.h:93" ], "poc_changes": "no seed; trigger written from scratch using the real _IOWR(T,202,struct tws_ioctl_no_data_buf) definition and pack(1) mirror structs", "attempts": 1, "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": 0, "guest_dirty": 0, "build_cmd": "cc -O2 -o trigger trigger.c", "run_cmd": "sudo ./trigger /dev/tws0 (host with tws controller; guest lacks device)", "notes": "Root-only ioctl path; corruption confined to the shared command DMA arena (no allocator metadata), victim is neighboring requests command headers incl. the request_id field trusted by tws_err_complete.", "recommended_fix": "Clamp gcmd->size against sizeof(union tws_command_giga)/4 minus the SGL extent before computing sgl_ptr in tws_dmamap_data_load_cbfn (and reject rather than submit oversized offsets).", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff bounds the SGL destination to the requests own giga packet; cannot be validated on the audit guest (no 3ware controller).", "fix_evidence": "fix.diff (guard in tws_dmamap_data_load_cbfn)", "code_hash": "05fa4764bb1f4d735353d1d65a7a76254f53a608c8021b727a859df20bea7768" } |