{
  "finding_id": "DF-5380",
  "status": "reproduced",
  "reproduced": true,
  "impact": "none",
  "confidence": "certain",
  "verdict": "usb_quirk_get_entry() returns the last dynamic-quirk slot unconditionally for the all-zero (vid|pid|lo|hi)==0 key and the slot-allocation path never clears quirks[], so the dynamic USB quirk table can be corrupted in two deterministic ways by a root ioctl (or boot kenv): (B) an all-zero ADD parks a quirk in the reserved slot while it still looks free, and that stale quirk is silently inherited by the real device entry that later allocates the slot (proven on guest: vid 0xa02d entry carried never-requested UQ_HID_IGNORE); (A) once the slot holds a real entry, all-zero ADD/REMOVE alias and mutate that live entry (proven: UQ_KBD_IGNORE appended to live vid 0xa02d; REMOVE can strip/free it). No memory-safety impact (all writes bounded inside quirks[8]); surface is root-only (verified EPERM for uid 1001). Severity Low. fix.diff validated on a rebuilt guest kernel: both scenarios gone, all-zero ADD against a live entry now EINVAL, normal add/get/remove unchanged.",
  "exploit_chain": "",
  "evidence": "run.log / run.2.log: SCENARIO_B_REPRODUCED: slot 383 holds real vid=0xa02d with STALE UQ_HID_IGNORE + UQ_CFG_INDEX_1 and SCENARIO_A_REPRODUCED: all-zero ADD appended UQ_KBD_IGNORE to LIVE entry; run.user.log: unprivileged ADD/REMOVE all EPERM; fix_run.log (kernel #1 Sat Oct 3 20:32:25): entry[383].sub[0]=UQ_CFG_INDEX_1 only (stale gone), all-zero ADD on live table rc=-1 EINVAL; fix_build.log: patched usb_quirk.c compiled with -Werror, Kernel build completed; VERDICT.md: full narrative + negative results.",
  "kernel_refs": [
    "sys/bus/u4b/quirk/usb_quirk.c:786",
    "sys/bus/u4b/quirk/usb_quirk.c:788",
    "sys/bus/u4b/quirk/usb_quirk.c:807",
    "sys/bus/u4b/quirk/usb_quirk.c:815",
    "sys/bus/u4b/quirk/usb_quirk.c:895",
    "sys/bus/u4b/quirk/usb_quirk.c:933",
    "sys/bus/u4b/quirk/usb_quirk.c:949",
    "sys/bus/u4b/quirk/usb_quirk.c:1050",
    "sys/bus/u4b/usb_dev.c:1707",
    "sys/kern/sys_generic.c:655"
  ],
  "poc_changes": "No seed PoC existed (pass-2 finding authored during verification). quirk_alias.c discovers the first free slot dynamically (expects 338), fills all 46 free slots with distinct vids, then proves stale-quirk inheritance (Scenario B) and live-entry aliasing (Scenario A) via USB_DEV_QUIRK_GET dumps, and cleans up; struct usb_gen_quirk and the _IOW/_IOWR commands were re-declared locally to match usb_ioctl.h exactly (7x uint16 + quirkname[50] = 64 bytes, group Q num 0-3).",
  "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 (baseline); patched: #1: Sat Oct 3 20:32:25 UTC 2026",
  "runtime_sec": 2,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -o /tmp/quirk_alias /tmp/quirk_alias.c",
  "run_cmd": "/tmp/quirk_alias   (as root on the guest; quirk table self-cleaning)",
  "code_hash": "c38d227b4bb8d1dd7e2b7f8dbe5ff071326dc7db9e49ee3c4cb7b7ad6c8e65bb",
  "notes": "338 static entries counted from source (commented Olympus macros excluded) -> 46 free boot slots 338..383; all-zero scratch = slot 383. Deterministic, race-free; reproduced twice on baseline. Negative results (killed): non-NUL quirkname strcmp (bounded by <=24-char NUL-terminated constants), usb_strquirk quirk[len] (len==strlen(quirk) whenever evaluated), GET index math (y<384, x<8), lock protocol (single leaf lock), probe-path info fields (compared, never used as indexes), strtou16/envkey sizing, module-unload tsleep grace (root-caused in usb_dynamic.c, not this file). DF-1047 not re-reported.",
  "recommended_fix": "In usb_quirk_get_entry(): return the reserved last slot for the all-zero key only while it is still free (else NULL), and memset quirks[] to zero when allocating a free slot.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Applied fix.diff to the guests /usr/src (pre-patch usb_quirk.c sha256 matched the audit tree), rebuilt with make nativekernel KERNCONF=X86_64_GENERIC (fix_build.log: patched usb_quirk.c compiled -Werror, build completed), installed, rebooted into kernel #1 Sat Oct 3 20:32:25 UTC 2026, re-ran the identical PoC: Scenario B no longer reproduces (slot 383 carries only UQ_CFG_INDEX_1, stale UQ_HID_IGNORE gone), all-zero ADD/REMOVE against the live table now fail with EINVAL instead of mutating it, and all 46 normal real-entry ADDs plus GET/REMOVE cleanup behave as before. Baseline (unpatched) reproduced both scenarios in the same run harness.",
  "fix_evidence": "fix_run.log: entry[383].sub[0]: UQ_CFG_INDEX_1 with SCENARIO_B_NOT_REPRODUCED (vid=0xa02d stale=0 real=1) and all-zero ADD UQ_KBD_IGNORE on live table -> rc=-1 (Invalid argument); fix_build.log: cc -c ... /usr/src/sys/bus/u4b/quirk/usb_quirk.c -Werror + >>> Kernel build for X86_64_GENERIC completed on Sat Oct 3 21:12:00 UTC 2026",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Sat Oct 3 20:32:25 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64"
}