DF-4157 / verdict.json
{ "finding_id": "DF-4157", "status": "untested", "reproduced": 0, "impact": "none", "confidence": "likely", "verdict": "aggch_feed_adc_stereo/mono derive their copy length solely from the APU CURPTR hardware register minus the base offset with no clamp; a desynced register (power-state TOCTOU: lockless ess->curpwr check in agg_intr vs agg_power(D3) under lock; or stop_adc racing a stale interrupt) underflows cur toward 2^32 and interleave()/mixdown() then write unboundedly past the 3*bufsz stat busdma buffer with recorded-audio contents. Source-certain absence of bounds; exploitability gated on Maestro hardware and hitting the desync window, hence likely/Medium. Guest has no Maestro device so untested.", "exploit_chain": "open /dev/dspN (0666) O_RDONLY -> AFMT_S16_LE stereo -> read loop drives PCMTRIG_EMLDMARD feeds -> concurrent suspend/resume or record stop/start churn hits the curpwr/CURPTR desync -> interleave() smashes kernel memory adjacent to the stat DMA allocation with attacker-recorded int16 pairs -> slab-groom a victim object adjacent -> uid=0 (ceiling; not demonstrated, no hardware)", "evidence": "maestro.c:1090-1104 (stereo feed, unclamped cur), maestro.c:1128-1139 (mono feed), maestro.c:1073-1081 (interleave writes 2 int16/iter), maestro.c:1653+1674-1676 (lockless curpwr gate then chn_intr dispatch), maestro.c:821-832 (D3 power-down under lock), maestro.c:1049-1053 (stop_adc clears active under lock), maestro.c:451-458 (wp_rdapu returns garbage on timeout, no error propagation), maestro.c:1829 (3*bufsz stat allocation); run.log (no maestro on guest)", "kernel_refs": ["sys/dev/sound/pci/maestro.c:1090", "sys/dev/sound/pci/maestro.c:1101", "sys/dev/sound/pci/maestro.c:1129", "sys/dev/sound/pci/maestro.c:1137", "sys/dev/sound/pci/maestro.c:1653", "sys/dev/sound/pci/maestro.c:821", "sys/dev/sound/pci/maestro.c:1049"], "poc_changes": "authored fresh probe (no seed); would-be trigger sketch documented in probe header", "attempts": 1, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 x86_64", "runtime_sec": 4, "guest_dirty": 0, "build_cmd": "cc -O -Wall -o /root/maestro_probe /root/maestro_probe.c", "run_cmd": "/root/maestro_probe; pciconf -lv | grep -i -A1 maestro; ls -l /dev/dsp*", "code_hash": "90980191770bbac49eb3cc3a67b94401e1f2bc9ebbda6523ee237a7bb554c469", "notes": "Nominal-operation consistency verified in source (LOOPLEN == ring sample capacity, base offsets match for all bufsz incl. 64K), so only register desync/power races break it. Also noted: calc_timer_div 32-bit overflow at extreme blksz and INVARIANTS-only speed!=0 guard are both unreachable via the PCM framework (chn_setparam clamps speed to caps 8000..48000 before the driver; sndbuf_resize enforces blkcnt*blksz<=maxsize).", "recommended_fix": "Clamp the register-derived cur to the ring bounds in both feed functions (treat desync as wrapped)", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "No Maestro hardware on the audit guest, so neither baseline corruption nor patched behaviour can be observed. fix.diff applies cleanly (git apply --check) and bounds cur to [0, ring) in both aggch_feed_adc_stereo and aggch_feed_adc_mono.", "fix_evidence": "findings/poc/DF-4157/fix.diff (git apply --check clean)" } |