DF-5506 / verdict.json
{ "finding_id": "DF-5506", "status": "reproduced", "reproduced": true, "impact": "dos", "confidence": "certain", "verdict": "REPRODUCED in-kernel against the unmodified production source: all three amdsmb poll-loop timeouts (ec_wait_write amdsmb.c:214-219, ec_wait_read :228-234, wait :287-293) are dead code \u2014 the post-decrement idiom exits with the counter at -1, so `if (x == 0)` never fires and SMB_ETIMEOUT (:293) is unreachable. A wedged SMB_PRTCL makes amdsmb_bread busy-spin 10002x500us=5.44s under the exclusive sc->lock and then return SMB_ENOERR with the PREVIOUS transactions data and count (run.log T1); a wedged IBF lets the driver keep writing to a non-consuming EC (T2); a wedged OBF makes it accept a stale EC data byte as any register value, e.g. SMB_BCNT (T2b). Fix.diff (detect exhaustion via x-- > 0 / x < 0 + propagate ec_read failures) validated in the same rig: fixed build returns SMB_ETIMEOUT / rc=1 and copies no data; the previously-dead device_printf timeout messages now execute; healthy path unchanged (T0 PASS both). Residual: 5.4s busy-wait remains (EC interface has no abort/KILL register). Hardware-gated (AMD-8111 1022:746a, absent from the guest and from every QEMU machine model) \u2014 evidence class is the production-code KLD harness with a stateful AMD-8111 EC register emulator (amdsmb.c asserted byte-identical to /usr/src at build time). Severity Low like the ichsmb DF-5461 / ig4 DF-5386 siblings.", "exploit_chain": "", "evidence": "run.log T1/T2/T2b (baseline: rc=0 fake success, 5440ms/10002 polls, stale 0xB0.. data accepted, stale 0x5C accepted as SMB_BCNT), run_fixed.log (rc=32 SMB_ETIMEOUT, rc=1, no data copied, dead printfs now fire), build.log:1 (production-source byte-identity assertion), amdh_harness.c (rig: #undef/#define bus_read_1/bus_write_1 before #include of the real amdsmb.c + EC/SMB register emulator), fix.diff, VERDICT.md", "kernel_refs": [ "sys/bus/smbus/amdsmb/amdsmb.c:212", "sys/bus/smbus/amdsmb/amdsmb.c:214", "sys/bus/smbus/amdsmb/amdsmb.c:216", "sys/bus/smbus/amdsmb/amdsmb.c:228", "sys/bus/smbus/amdsmb/amdsmb.c:230", "sys/bus/smbus/amdsmb/amdsmb.c:287", "sys/bus/smbus/amdsmb/amdsmb.c:291", "sys/bus/smbus/amdsmb/amdsmb.c:293", "sys/bus/smbus/amdsmb/amdsmb.c:297", "sys/dev/smbus/smb/smb.c:318" ], "poc_changes": "no seed existed (pass-2 fresh finding); authored the production-code KLD harness: #include of the real amdsmb.c with bus_read_1/bus_write_1 redirected into a stateful AMD-8111 EC register emulator, fake device_t/resource/softc, tests T0-T4 executed at MOD_LOAD", "attempts": 4, "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": 660, "guest_dirty": 0, "build_cmd": "guest# cd /root/amdh && sh build.sh (asserts amdsmb.c == /usr/src production source; make -Werror clean)", "run_cmd": "guest# sh /root/amdh/run.sh (kldload ./amdh.ko; tests at MOD_LOAD; dmesg capture); fixed: sh build.sh fixed && sh run.sh", "code_hash": "b0e9c85827e67bbe351278d8ae6f4af488a5741ef1e6d5a1f1e5d8b1606777c9", "notes": "Attempts=4 kldload runs (2 interim builds during harness instrumentation, final baseline, fixed). The 3 harness self-failures in run_fixed.log are the three bug-reproduction asserts reading NOT-reproduced in the fixed build \u2014 i.e. the fix working. SMB_ETIMEOUT=0x20, SMB_EINVAL=0x100 per sys/bus/smbus/smbconf.h:55-63. Guest left with amdh module unloaded; vm.sh reset with-src performed at end of run.", "recommended_fix": "amdsmb.c: fix all three poll loops to detect exhaustion (`while (x-- > 0 && cond)` + `if (x < 0)`), propagate amdsmb_ec_read/write failures in amdsmb_wait as SMB_EBUSERR \u2014 exactly fix.diff; validated in-rig.", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "Baseline reproduced (rc=0 fake success with stale data after 5440ms; dead SMB_ETIMEOUT). Patched build (fix.diff applied to harness copy, /usr/src untouched): T1 returns SMB_ETIMEOUT with zero data copied, T2/T2b return rc=1 with the timeout messages now firing, healthy-path T0 unchanged. The bad behavior is gone.", "fix_evidence": "run.log vs run_fixed.log (T1/T2/T2b lines); build_fixed.log; fix.diff" } |