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)
PoC verification
Evidence pack
findings/poc/DF-5027 Β· 6 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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)
ips_get_free_cmd()hands out a command withstatusbzero'd (ips.c:232), soCOMMAND_ERROR(&command->status)(basic_status 0 < 2) can never fire until a completion fills it.ipsd_dump_map_sgissues the command and callssc->ips_poll_cmd(command)(ips_disk.c:321-322).- 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. ipsd_dumpthen checks onlyCOMMAND_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)).- 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).
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_cmdbzeroescommand->statuson 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->completedis 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_testablefix.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
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).
No comments yet.