DF-2351 / verdict.json
{ "finding_id": "DF-2351", "status": "reproduced", "verdict": "REPRODUCED \u2014 deterministic kernel NULL-deref panic at device attach, driven through the unmodified production uvc parse/attach functions. Kernel log proves the exact claimed truncation: uvc_drv_init_data_fmt counted nfmt=256 (uint16_t local), allocated the correctly sized 24KB buffer, then stored data->nfmt=0 (uint8_t field). uvc_drv_parse_data completed with data->nfmt==0; uvc_drv_init_cur_fmt_frm skipped its search loop, left fmt==NULL, and faulted reading fmt->nfrm (uvc_drv.c:1463): Fatal trap 12, fault virtual address = 0x8 (offsetof nfrm), stopped at uvc_drv_init_cur_fmt_frm.cold.36: movq 0x8,%rax. FIX VALIDATED on the same rig: with fix.diff (uint16_t fields + NULL guards) data->nfmt stores 256 and init_cur_fmt_frm returns EINVAL \u2014 no panic.", "reproduced": true, "impact": "panic", "confidence": "certain", "exploit_chain": "Malicious USB webcam with 256 VS_FORMAT_MJPEG descriptors (2869-byte config descriptor, fits 65535 limit) -> attach -> uvc_drv_parse_ctrl -> uvc_drv_parse_data -> uvc_drv_init_data_fmt stores truncated nfmt=0 (allocation correct) -> device answers GET_DEF/GET_CUR probe (attacker-controlled) -> uvc_drv_init_video -> uvc_drv_init_cur_fmt_frm NULL fmt -> fmt->nfrm read at address 0x8 -> kernel panic. No privilege or user interaction needed beyond device attach; pure DoS (NULL read), no disclosure/control-flow impact.", "evidence": "panic.txt lines: stored data->nfmt=0 ... fmt=0xfffff80118496000 <-- TRUNCATION, Fatal trap 12 ... fault virtual address = 0x8, Stopped at uvc_drv_init_cur_fmt_frm.cold.36: movq 0x8,%rax. fix_run.log: stored data->nfmt=256, init_cur_fmt_frm returned 22 -- NO PANIC.", "kernel_refs": [ "sys/bus/u4b/uvc/uvc_drv.c:1674", "sys/bus/u4b/uvc/uvc_drv.c:1737", "sys/bus/u4b/uvc/uvc_drv.c:1457", "sys/bus/u4b/uvc/uvc_drv.c:1463", "sys/bus/u4b/uvc/uvc_drv.c:1528", "sys/bus/u4b/uvc/uvc_drv.h:662" ], "poc_changes": "No PoC seed existed. Built the KLD rig from scratch: rig/uvc_rig.c #includes the four unmodified production uvc sources and fabricates only struct usb_device (cdesc + ifaces). Two early rig-blob bugs fixed during bring-up (VS_FORMAT_MJPEG descriptors must be 11 bytes; VS INPUT HEADER bLength=13) \u2014 the panic site reproduced even with the first malformed blob (init_data_fmt EINVAL also leaves nfmt==0), but the final run proves the exact truncation path with init_data_fmt ret=0.", "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": 240, "guest_dirty": 0, "build_cmd": "./build.sh (setup.sh: make in guest /usr/src/sys/bus/u4b/uvc/rig -> uvc_rig.ko, gcc 8.3 -Werror clean; cc -O2 -o /tmp/trigger_sparm)", "run_cmd": "kldload uvc_rig.ko; sysctl hw.usb.uvcrig=2351 -> panic (see run.sh)", "code_hash": "a472ed15602cd9a5a5b0a6159c93f973023350dce71f2777a28fa6d29726e027", "notes": "Evidence class: production-handler KLD dispatch rig \u2014 descriptor parsing through the panic is 100% in-tree code; the rig synthesizes only the USB transport (QEMU has no emulated UVC webcam). uvc is a KLD-only driver on this guest (not in X86_64_GENERIC), so module-level rebuild is the production fix vehicle. Guest left up and clean (reset with-src; rig dir removed; module unloaded).", "recommended_fix": "Widen uvc_drv_data.nfmt/nfrm/nitv to uint16_t and add fmt==NULL guards in uvc_drv_init_cur_fmt_frm and the init_video GET_CUR fallback", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "Patched rig (fix.diff applied to guest /usr/src, module rebuilt -Werror clean) stores data->nfmt=256 and returns EINVAL from uvc_drv_init_cur_fmt_frm: no panic, guest stays up. Baseline vs patched differ only by fix.diff.", "fix_evidence": "fix_run.log: stored data->nfmt=256 ... fmt=0xfffff80118660000, No frame desc found for default format., init_cur_fmt_frm returned 22 -- NO PANIC; fix_build.log: patched uvc_rig.ko builds clean under -Werror." } |