DF-5543 / verdict.json
{ "finding_id": "DF-5543", "status": "reproduced", "reproduced": true, "impact": "dos", "confidence": "certain", "verdict": "REPRODUCED (deterministic, 2/2 runs, hardware-free). In uep_intr_callback(), when a continuation consumes res bytes to complete a pending packet (uep.c:225-231, p = buf + res), the one-remaining-byte stash stores buf[0] - the already-consumed first byte of this transfer - instead of the remaining byte p[0] (uep.c:236). Demonstrated with a 6-byte PRESSURE-class packet split 5+2: the 2-byte transfer {0x81,0xAA} completes the pressure packet with 0x81 and leaves 0xAA, but 0x81 is stashed; the next transfer then reassembles and vends the FABRICATED report 81:bb:cc:dd:ee while the true stream byte 0xAA disappears from the stream entirely (silent touch-input corruption: coordinates computed from duplicated/misaligned bytes, uep.c:180-181). With a consumed byte that is a bad header (0x55), the mis-stash arms DF-5542s permanent stall (cascade, T4). Any legitimate eGalax controller emitting 6-byte reports with 5+2 transfer splits hits this boundary with well-formed traffic. Production-code KLD harness (unmodified uep.c, sha256-verified). fix.diff hunk 2 (p[0]) validated: no fabricated report, true byte stashed, proper header-resync; patched file also builds as the real uep.ko under -Werror; guest restored to stock.", "exploit_chain": "malicious USB device (or any real controller whose 6-byte PRESSURE/PLAYER reports split 5+2 across interrupt transfers) -> continuation completes a packet leaving exactly 1 byte in the transfer -> uep.c:236 stashes the consumed buf[0] instead of p[0] -> next transfer reassembles a shifted 5-byte report: fabricated coordinates vended on /dev/uep0, one real byte dropped; if the consumed byte is a bad header -> DF-5542 permanent wedge. Input-integrity/availability only: no memory unsafety, no escalation path.", "evidence": "run.log/run.2.log (stock, identical): T3 stash queued_reports=1 report0=81:bb:cc:dd:ee aa_dropped=1 verdict=WRONG_BYTE_STASHED and T4 cascade ... verdict=PERMANENT_STALL; fix_run.log: T3 ... queued_reports=0 ... verdict=correct (true byte stashed, candidate rejected by the uep.c:154 format check) and T4 ... verdict=no_stall; fix_build.log (real uep.ko with fix, -Werror); env.txt (uname + production sha256); VERDICT.md (byte-level trace)", "kernel_refs": [ "sys/bus/u4b/input/uep.c:230", "sys/bus/u4b/input/uep.c:231", "sys/bus/u4b/input/uep.c:235", "sys/bus/u4b/input/uep.c:236", "sys/bus/u4b/input/uep.c:180", "sys/bus/u4b/input/uep.c:181", "sys/bus/u4b/input/uep.c:154" ], "poc_changes": "No seed PoC existed (new pass-2 finding); harness authored from scratch and shared with DF-5542 (see that verdicts poc_changes).", "attempts": 2, "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": 1560, "guest_dirty": 0, "build_cmd": "guest root: cd /root/ueph && cp /usr/src/sys/bus/u4b/input/uep.c uep.c && make (see build.sh)", "run_cmd": "guest root: kldload ./ueph.ko; sleep 1; kldunload ueph; dmesg | grep UEPH: (see run.sh)", "code_hash": "e72b11536c427a58e9be7b435de0901be91e2997216d9df139969986448370bf", "notes": "Shared harness/module with DF-5542; impact recorded as dos (DB enum) with the integrity nuance (fabricated reports + dropped bytes) documented in VERDICT.md. No escalation path: the primitive only shifts parser alignment. FreeBSD uep.c carries the same defect (imported code). Guest /usr/src restored to stock after fix validation; module unloaded.", "recommended_fix": "Stash the remaining stream byte: sc->buf[0] = p[0] (plus DF-5542s buf_len reset and the uep_close() state reset) - see fix.diff.", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "Patched production file (fix.diff, guest /usr/src copy): T3 verdict=correct - no fabricated 81:bb:cc:dd:ee report, the true remaining byte 0xAA is stashed and its 5-byte candidate is correctly rejected by the format check (header resync); T4 no_stall with 13 reports aligned to the true stream. Stock behavior restored afterwards (sha256 match).", "fix_evidence": "fix.diff; fix_build.log (harness + real uep.ko build, -Werror clean); fix_run.log (T3 stash queued_reports=0 ... verdict=correct, T4 cascade queued_reports=13 ... verdict=no_stall)" } |