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

ciss_init_pci: unvalidated firmware transport_offset maps ciss_perf outside the BAR window; ciss_init_perf writes through it

Summary

sc->ciss_perf = (cbase + cofs + sc->ciss_cfg->transport_offset) uses a firmware-controlled u32 with no window check (the existing check covers only the config table itself); ciss_init_perf then writes the fetch table, rq_size/rq_count and reply-queue addresses through that pointer - arbitrary-offset write relative to the BAR mapping on malicious/corrupted controller memory or a spoofed Smart Array on external PCIe. Upstream-inherited. Malicious/buggy-hardware threat model only. Fix compile-validated.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3732 Β· 8 files
FileTypeDescriptionSize
VERDICT.md verdict full narrative: mechanism, path:line, harness proof, fix 2.8 KB ↓ raw
fix.diff suggested-fix validate cfg->transport_offset against the BAR window before mapping ciss_perf; else fall back to simple transport 651 B view raw
fix_apply.log apply-log patch --dry-run on guest /usr/src (clean) 2.8 KB view raw
fix_build.log build-log ciss.ko rebuilt with all 7 pass-2 fixes at -Werror, link rc=0 1.0 KB view raw
env.txt environment guest uname, no-HW proof, module presence 538 B view raw
README.md readme human reproduce doc 1.5 KB ↓ raw
manifest.json manifest this file 1.9 KB view raw
verdict.json verdict machine verdict (persist_poc.py schema) 2.2 KB view raw
README.md readme human reproduce doc
↓ download raw

DF-3732 β€” ciss_init_pci: firmware-controlled transport_offset maps the Performant table outside the BAR window; ciss_init_perf writes through it

File: sys/dev/raid/ciss/ciss.c:692-695 β€” sc->ciss_perf = (struct ciss_perf_config *)(cbase + cofs + sc->ciss_cfg->transport_offset); with no bound on transport_offset (the config-table check at ciss.c:646 validates only cofs + sizeof(struct ciss_config_table) <= csize). ciss_init_perf then writes the fetch table, queue sizes and reply-queue address through that pointer (ciss.c:926-946).

Class: OOB write relative to the mapped BAR (CWE-787), fully firmware/PCIe-device controlled (malicious or corrupted controller memory / spoofed Smart Array on external PCIe). Upstream-inherited (FreeBSD has the identical code). Severity Low (malicious-hardware threat model; no unprivileged-local or remote trigger).

Verification status

Source-level certainty; inconclusive at runtime β€” the audit guest has no HP Smart Array PCI device (env.txt), so neither the vulnerable mapping nor the fix can be exercised live. The one-line bounds check in fix.diff mirrors the existing ciss.c:646 pattern.

Fix

fix.diff (validate cofs + transport_offset + sizeof(struct ciss_perf_config) <= csize, else fall back to the simple transport). Compile-validated: applied together with the 6 other ciss pass-2 fixes, ciss.ko rebuilt at -Werror, link rc=0 (fix_build.log, fix_apply.log).

Artifacts

VERDICT.md, fix.diff, fix_apply.log, fix_build.log, env.txt, manifest.json, verdict.json.

VERDICT.md verdict full narrative: mechanism, path:line, harness proof, fix
↓ download raw

DF-3732 VERDICT

Finding

During attach, ciss_init_pci() bounds-checks the CISS config table location (cofs + sizeof(struct ciss_config_table) > csize β†’ ENXIO, ciss.c:646-649), then selects the Performant transport by pointer arithmetic on a second, unvalidated firmware field:

    /* sys/dev/raid/ciss/ciss.c:692-695 */
setup:
    if ((supported_methods & CISS_TRANSPORT_METHOD_PERF) != 0) {
    method = CISS_TRANSPORT_METHOD_PERF;
    sc->ciss_perf = (struct ciss_perf_config *)(cbase + cofs +
        sc->ciss_cfg->transport_offset);      /* 32-bit FW value, unchecked */

transport_offset is a u_int32_t read out of adapter-mapped memory (cissreg.h:414). Nothing constrains it to the BAR window (csize). With a malicious/corrupted controller (or a spoofed Smart Array function on externally-attacker-reachable PCIe, e.g. Thunderbolt-era chassis), sc->ciss_perf can point anywhere within ~4 GB of the mapping base β€” and ciss_init_perf() immediately writes through it:

    /* sys/dev/raid/ciss/ciss.c:926-946 */
    pc->fetch_count[...] = ...;      /* 8 x u32 writes */
    pc->rq_size  = sc->ciss_max_requests;
    pc->rq_count = 1;
    pc->rq_bank_hi/lo = 0;
    pc->rq[0].rq_addr_hi/lo = ...;   /* host phys addresses written OOB */

Impact: arbitrary-offset kernel memory corruption relative to the BAR mapping (write of semi-controlled content: small integers + host physical addresses). Threat model is malicious/buggy hardware β€” the same trust boundary the rest of this driver's firmware-parsing findings use, but here there is no unprivileged-local or remote software trigger at all, hence Low.

Status

  • Source-certain (the missing check is unambiguous; FreeBSD upstream has the same gap).
  • Runtime: inconclusive β€” the audit guest has no HP Smart Array PCI device (env.txt: pciconf -l | grep -i 0e11|103c β†’ NONE), so neither the vulnerable path nor the fix is live-testable.

Fix validation

  • fix.diff adds the window check (mirroring the ciss.c:646 pattern) and falls back to the SIMPLE transport when it fails.
  • fix_apply.log: patch --dry-run clean on the guest's /usr/src; fix_build.log: ciss.ko rebuilt with all 7 ciss pass-2 fixes at -Werror, link rc=0. No behavioral run possible (no hardware).

Bottom line: inconclusive at runtime (hardware absent), source-certain missing bounds check on a firmware-controlled pointer used for writes; fix compile-validated.

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

inconclusive
baseline no→ patch + rebuild →patched clean

Bounds check added (cofs+transport_offset+sizeof(perf config) <= csize, else fall back to SIMPLE). Compile-validated only: -Werror module build with all 7 fixes, link rc=0. No behavioral run possible (hardware absent).

fix.diff; fix_apply.log; fix_build.log
↓ fix.diffper-fix-DF-3732

Confirmed kernel references

Detail

Exploit chain

malicious/corrupted controller config table -> transport_offset out of window -> ciss_init_perf writes OOB of mapping

Evidence (decisive lines)

VERDICT.md path analysis; env.txt (no HP PCI devices); fix_apply.log + fix_build.log

PoC changes

no runnable PoC possible without the device; source-level pack

Verified recommended fix

validate cfg->transport_offset against the BAR window before mapping ciss_perf; else fall back to simple transport

Verdict

INCONCLUSIVE at runtime (no HP Smart Array PCI device on the guest - env.txt), source-certain: sc->ciss_perf is computed as cbase+cofs+cfg->transport_offset (ciss.c:694-695) from an unvalidated firmware u32 (only the config table itself is checked at ciss.c:646) and ciss_init_perf writes the fetch table/queue config through it (ciss.c:926-946) -> arbitrary-offset write relative to the BAR on malicious/buggy hardware. Low severity (malicious-hardware threat model). Upstream-inherited.