β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4808

dce110 i2c hw engine: SW engine-state accounting desync corrupts subsequent DDC/I2C transactions β€” write-path buffer_used_bytes undercounts (length consumed before the accounting add), counters never reset on aborted-busy/release paths, and I2C_HW_BUFFER_SIZE=538 exceeds the 8-bit DC_I2C_INDEX/COUNT0 fields

Summary

WRITE transactions account only the address byte (the length is zeroed by the write loop before the accounting add) so free-space is overstated for MOT batches; counters/TRANSACTION registers only reset on the success path, so a busy-abort or release poisons the next acquire (INDEX_WRITE skipped, aborted chain re-executed - garbage DDC/EDID until some chain completes); 538-byte buffer vs 8-bit fields (latent truncation). No kernel memory unsafety (caller-sized writes); upstream twin. Account-original + reset-on-release + clamp fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4808 Β· 1 files
FileTypeDescriptionSize
verdict.json file 1.7 KB view raw

Fix verification

not_testable
per-fix-DF-4808

Confirmed kernel references

Detail

Exploit chain

interleave a multi-payload WRITE-MOT DDC batch with a busy engine (submit_channel_request is_hw_busy path) -> next EDID read executes against stale TRANSACTION registers and stale DC_I2C_INDEX base -> corrupted EDID / persistent DDC failure

Evidence (decisive lines)

findings/poc/DF-4808/ (this verdict)

Verdict

Hardware-gated data-integrity defect (no kernel memory unsafety - all writes caller-sized): three coupled accounting defects in the DCE110 hw I2C engine - (1) process_transaction zeroes its local length in the write loop then accounts buffer_used_bytes += length+1, so WRITE transactions account only the address byte and get_hw_buffer_available_size overstates free space for MOT batches (the submit_request guard admits more than the HW circular buffer holds); (2) counters/DC_I2C_TRANSACTIONn registers only reset in execute_transaction - an ENGINE_BUSY abort or release between sub-transactions leaves stale state so the next acquire lands payloads with INDEX_WRITE skipped and re-executes the aborted chain (garbage DDC/EDID traffic until some chain completes); (3) I2C_HW_BUFFER_SIZE=538 exceeds the 8-bit DC_I2C_INDEX/COUNT0 field masks (latent truncation >255). Upstream twin exists (Linux dce110/dce80 identical). No AMD GPU on guest - skipped per Low severity. Account-original-length + reset-on-release + clamp fix.