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

ipsd_dump() reports fake success when ips_poll_cmd never completes β€” copperhead crash dumps can be silently empty/corrupt (zeroed status defeats COMMAND_ERROR)

Summary

The dump command goes out with bzero'd status so COMMAND_ERROR can never fire, and the copperhead poll is an unimplemented stub - every 64K chunk reports success while no completion ever arrives (plus per-iteration dmamap re-load UB). savecore believes an empty/corrupt dump. Distinct from DF-4616 (timing). Hardware-gated; deterministic source chain. Completed-flag handshake fix compile-validated.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-5027 Β· 6 files
FileTypeDescriptionSize
env.txt β€” 400 B view raw
fix.diff β€” 936 B view raw
fix_validation.log β€” 1.8 KB view raw
README.md β€” 2.0 KB ↓ raw
VERDICT.md β€” 2.0 KB ↓ raw
verdict.json β€” 3.7 KB view raw

DF-5027 β€” ipsd_dump() reports fake success when the poll never completes (ips_disk.c)

File: sys/dev/raid/ips/ips_disk.c (pass 2) Lines: 249-271 (dump loop), 261-264 (COMMAND_ERROR on a zeroed status), 326-336 (completion callback that never runs on copperhead) Class: crash-dump integrity / silent data loss (CWE-252 / CWE-754); sibling of DF-4616 (morpheus poll-window), distinct mechanism (copperhead poll is a stub) and distinct file.

Mechanism (source, deterministic on copperhead)

  1. ips_get_free_cmd() hands out a command with status bzero'd (ips.c:232), so COMMAND_ERROR(&command->status) (basic_status 0 < 2) can never fire until a completion fills it.
  2. ipsd_dump_map_sg issues the command and calls sc->ips_poll_cmd(command) (ips_disk.c:321-322).
  3. On copperhead adapters ips_poll_cmd = ips_copperhead_poll β€” an unimplemented stub that only kprintfs (ips.c:810-814). No completion is ever delivered; ipsd_dump_block_complete (which would unload the map) never runs.
  4. ipsd_dump then checks only COMMAND_ERROR (ips_disk.c:261-264) β€” sees the zeroed status, judges success, and loops: re-issuing into a command slot the adapter may still own and re-bus_dmamap_loading a map that was never unloaded (undefined per bus_dma(9)).
  5. Result: a copperhead crash dump can be an empty/interleaved-corrupt file while every block reported success β€” forensics/dump confidentiality- relevant integrity loss, silently.

Why not reproduced at runtime

Dump path needs an IPS adapter (absent β€” env.txt) AND a crash dump. The code chain is unconditional (no timing): stub β†’ zeroed status β†’ false success.

Fix

fix.diff: ipsd_dump_block_complete sets command->completed = 1; the dump loop requires completed != 0 (else EIO + break) and resets the flag per iteration. Copperhead dumps now fail loudly (EIO) instead of lying; morpheus dumps are unaffected (poll delivers the completion). Compile- validated in the patched ips.ko build (-Werror clean).

VERDICT.md
↓ download raw

DF-5027 Verification Verdict

Status: not_reproduced (hardware-gated crash-dump path; code chain deterministic β€” stub poll + zeroed status + unchecked completion)

Source proof

  • ips.c:232 β€” ips_get_free_cmd bzeroes command->status on handout.
  • ips.c:810-814 β€” ips_copperhead_poll: "cmd polling not implemented for copperhead devices" β€” kprintf and return; the issued dump command is never completed, ipsd_dump_block_complete (ips_disk.c:326-336) never runs, the data map is never unloaded.
  • ips_disk.c:261-264 β€” the ONLY post-issue check is COMMAND_ERROR(&command->status) on that still-zeroed status β†’ always false β†’ every 64K chunk "succeeds"; command->completed is never consulted.
  • Follow-on: ips_disk.c:256-257 re-loads an already-loaded dmamap on the next loop iteration (bus_dma(9) undefined behavior).

Distinction from known findings: DF-4616 covers the morpheus poll window being 10x too short (ips.c timing bug); this finding is the copperhead complete no-op plus ipsd_dump's missing completion check β€” different adapter, different file, different failure (false success vs short wait).

Not exercisable on this guest

No IBM ServeRAID adapter (env.txt: no 0x1014/0x9005 PCI devices, no /dev/ips*, no ipsd disks); the dump path additionally requires a crash. The defect is unconditional control flow, hence confidence certain in the code; runtime reproduction hardware-gated.

Fix validation

fix.diff (completed-flag handshake) compiled clean as part of the patched ips.ko module build (-Werror, fix_validation.log). Behavioral validation hardware-gated β†’ fix_status not_testable.

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.diff compile-validated as part of the merged patched ips.ko module build on the guest (-Werror clean, fix_validation.log in DF-5026's pack; sources restored). Behavioral validation is hardware-gated (no copperhead adapter, and exercising it needs a crash dump), so the fix cannot be exercised end-to-end.

fix.diff; patched ips.ko build log (fix_validation.log, referenced from DF-5026 pack); VERDICT.md fix section
↓ fix.diffper-fix-DF-5027

Confirmed kernel references

Detail

Evidence (decisive lines)

env.txt (hardware-absence probe: no IPS PCI devices, no /dev/ips*, no ipsd disks); VERDICT.md trace: ips.c:232 bzero + ips.c:810-814 stub + ips_disk.c:261-264 zeroed-status check + ips_disk.c:326-336 callback that never runs

PoC changes

no runtime PoC possible; hardware-absence probe captured as env.txt evidence

Verified recommended fix

ipsd_dump_block_complete: set command->completed = 1; ipsd_dump loop: require completed != 0 (else EIO + break) and reset the flag per iteration, so a poll that never delivers (copperhead stub) fails the dump loudly instead of reporting fake success (fix.diff).

Verdict

Source-verified, deterministic crash-dump integrity defect; runtime reproduction impossible on this guest (needs an IBM ServeRAID copperhead adapter AND a crash dump; env.txt shows no IPS hardware). ips_get_free_cmd hands out commands with status bzero'd (ips.c:232); on copperhead adapters ips_poll_cmd is an unimplemented stub that only kprintfs (ips.c:810-814), so after ipsd_dump_map_sg issues each dump chunk (ips_disk.c:321-322) no completion is ever delivered -- ipsd_dump_block_complete never runs and the data map is never unloaded -- yet the dump loop's only post-issue check, COMMAND_ERROR(&command->status) (ips_disk.c:261-264), tests the still-zeroed status and always passes: every 64K chunk reports success. A copperhead crash dump can therefore be empty or corrupt (chunks issued back-to-back into a command slot the adapter may still own, plus re-loading an already-loaded bus_dmamap at ips_disk.c:256-257, undefined per bus_dma(9)) while savecore believes it valid. Sibling of DF-4616 (morpheus poll window 10x too short -- timing bug in ips.c); this is a different mechanism (complete no-op stub) rooted in ips_disk.c's missing completion check. fix.diff (completed-flag handshake: ipsd_dump_block_complete sets command->completed=1, the loop requires it and resets per iteration) compiled clean in the patched ips.ko build (-Werror).