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

adv_send_scsi_queue computes the per-queue sense DMA bus address from unvalidated firmware-LRAM free_q_head β€” device-DMA write outside sense_buffers (write-side twin of DF-2412)

Summary

The free-queue head (u8 0..255) read from RISC-shared LRAM is used unchecked to set q1.sense_addr = sense_physbase + (free_q_head-1)*32. The sense arena is sized exactly max_openings slots (<=240): free_q_head==0 targets 32 bytes BELOW the allocation; >max_openings targets up to +8128 on a <=7680-byte arena. On CHECK CONDITION the RISC engine DMAs sense data (unclamped length) to that address. Same RISC-state trust model as DF-2412/2414. Clamp-to-range fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4151 Β· 4 files
FileTypeDescriptionSize
trigger_sense_dma.c trigger Illustrative trigger (hardware-gated) 2.0 KB view raw
VERDICT.md verdict Full source-trace analysis 3.8 KB ↓ raw
fix.diff suggested-fix Clamp free_q_head to [ADV_MIN_ACTIVE_QNO, adv->max_openings] in adv_send_scsi_queue before computing sense_addr/q_no. 690 B view raw
env.txt environment Guest uname + pciconf hardware-gate proof 980 B view raw
VERDICT.md verdict Full source-trace analysis
↓ download raw

DF-4151 β€” Unvalidated RISC-LRAM free_q_head selects the sense DMA bus address (write-side twin of DF-2412)

File: sys/dev/disk/advansys/advlib.c (pass 2)

Reproduced?

No β€” hardware-gated. The QEMU audit guest (DragonFly 6.5-DEVELOPMENT X86_64_GENERIC) has no AdvanSys HBA: pciconf -l shows only i440fx/PIIX4, virtio-net, virtio-blk and a virtio VGA (chip 0x1111:1234); no 0x10cd/0xCD AdvanSys device and no adv driver attachment in dmesg (see env.txt). The defect is established at source level.

Source trace

adv_send_scsi_queue() (sys/dev/disk/advansys/advlib.c:1700-1727) reads the free-queue head from firmware-shared LRAM and uses it directly as a queue index:

1709:  free_q_head = adv_read_lram_16(adv, ADVV_FREE_Q_HEAD_W) & 0xFF;   /* u8: 0..255 */
1710:  if ((next_qp = adv_alloc_free_queues(adv, free_q_head, n_q_required))
1711:      != ADV_QLINK_END) {
1712:          scsiq->q1.q_no = free_q_head;
1719:          scsiq->q1.sense_addr = adv->sense_physbase
1720:              + ((free_q_head - 1) * sizeof(struct scsi_sense_data));

The DMA sense arena is allocated for exactly max_openings sense slots: advansys.c:1345 (sizeof(struct scsi_sense_data) * adv->max_openings tag) and advansys.c:1363-1366 (load of the same size; sense_physbase is the bus address of adv->sense_buffers). max_openings is clamped to ADV_MAX_TOTAL_QNG = 240 (advansys.c:843-852), so the arena is at most 32 * 240 = 7680 bytes.

Invariant required for safety: free_q_head ∈ [1, max_openings]. Nothing enforces it:

  • free_q_head == 0 β†’ sense_addr = sense_physbase - 32: the RISC engine DMAs CHECK-CONDITION sense data 32 bytes below the allocation.
  • free_q_head > max_openings (up to 255) β†’ sense_addr up to sense_physbase + 254*32 = +8128, i.e. up to ~448 bytes past the end of a 7680-byte arena (proportionally more headroom for smaller max_openings; e.g. a 16-slot INRAM config (512 bytes) gives a 7.6 KB window past the end).

adv_alloc_free_queues() (advlib.c:1669-1698) only follows FWD links and returns ADV_QLINK_END when the head slot has QS_READY set β€” it never range-checks the head value itself. The companion read-side index (adv->sense_buffers[q_no - 1] in advansys.c:1185-1186) is the already filed DF-2412; this is the write-side (DMA target address) twin at a different site in a different file, with a strictly stronger primitive (32+ bytes of device-written data at a corrupted bus address vs. a read-only struct copy).

The DMA length is separately unclamped (q1.sense_len = csio->sense_len, DF-1546), so the write length is also attacker-of-firmware-chosen up to 255.

Threat model / preconditions

Same trust model already accepted by this audit for DF-2412 / DF-2414: the value lives in RISC-maintained LRAM, so the trigger is (a) a firmware bug or LRAM desync (e.g. queue-state corruption after hostile-target-induced malfunction β€” the mechanism DF-2414 documents), or (b) a genuinely hostile HBA. The guest has no such HBA, so no runtime trigger is possible here. Impact if triggered: device-DMA write of sense bytes into kernel heap adjacent to sense_buffers β€” memory corruption (bounded window, partially attacker-influenced content via a hostile target's sense data).

Verdict

INCONCLUSIVE (hardware-gated / not reachable on the audit guest). Source defect is real and certain; exploitability requires AdvanSys ASC hardware with corrupted firmware queue state. Severity Low (hardware-gated, firmware-trust precondition), same tier as DF-2412.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

Fix not testable: single-fix kernel build cannot exercise adv(4)/amdgpu paths without the respective hardware on the guest.

fix.diff authored post-verification from line-accurate source trace (VERDICT.md); env.txt documents absent hardware.
↓ fix.diffper-fix-DF-4151

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md (source trace + precondition), fix.diff (clamp), env.txt (guest pciconf: no AdvanSys).

PoC changes

Seed replaced with an honest hardware-gated trigger sketch/mutator; no runnable PoC exists for this defect class on the audit guest.

Verified recommended fix

Clamp free_q_head to [ADV_MIN_ACTIVE_QNO, adv->max_openings] in adv_send_scsi_queue before computing sense_addr/q_no.

Verdict

INCONCLUSIVE (hardware-gated). advlib.c:1709-1720 uses firmware-LRAM free_q_head unchecked to compute the per-queue sense DMA bus address; value 0 or >max_openings makes the adapter DMA sense data outside the sense_buffers arena (32B below to ~448B past a 7680B alloc). Write-side twin of DF-2412. No AdvanSys HBA on the audit guest (pciconf in env.txt) so no runtime trigger; defect certain at source level under the audit's established RISC-state trust model (DF-2414).