DF-4639 / verdict.json
{ "finding_id": "DF-4639", "status": "reproduced", "reproduced": 1, "impact": "none", "confidence": "certain", "verdict": "ips_send_flush_request (ips_commands.c:202-206) is inverted against its own debug knob: with the DEFAULT value debug.ips.ignore_flush_cmd=0 (static BSS + TUNABLE_INT, ips_commands.c:35-36; confirmed live on the guest kernel, which has ips compiled in) the function frees the command slot and completes the BUF_CMD_FLUSH bio with no error WITHOUT ever building/issuing IPS_CACHE_FLUSH_CMD; the real adapter cache-flush (opcode 0x0A, ips_commands.c:210-218) only runs when the flag is SET - the exact opposite of the sysctl description Do not issue IPS_CACHE_FLUSH_CMD on BUF_CMD_FLUSH (ips_commands.c:40). Reproduced on the guest from an unprivileged account with a verbatim extraction of the branch (run.log: flag=0 -> 0 adapter commands, bio finished no-error; flag=1 -> 1 command opcode 0x0a; exit 42). Net effect on stock systems: every flush bio on an ips disk (fsync on the raw device, filesystem/unmount flushes via ipsd_strategy -> ips_start_io_request, ips_commands.c:249-250) reports durability while the adapter write cache is never flushed - power-loss data loss after a returned fsync. impact=none in the poc sense (no kernel memory corruption / privilege effect); the harm is silent data-integrity violation. The whole flush-request block is DragonFly-specific (no such tunable or function in FreeBSD upstream).", "exploit_chain": "", "evidence": "run.log (live sysctl default 0 + harness both cases + exit 42), flush_invert_harness.c (verbatim branch extraction), VERDICT.md proof chain with ips_disk.c:128-140/ips_commands.c:35-40,195-220,249-252, fix.diff", "kernel_refs": [ "sys/dev/raid/ips/ips_commands.c:35", "sys/dev/raid/ips/ips_commands.c:40", "sys/dev/raid/ips/ips_commands.c:196", "sys/dev/raid/ips/ips_commands.c:202", "sys/dev/raid/ips/ips_commands.c:210", "sys/dev/raid/ips/ips_commands.c:218", "sys/dev/raid/ips/ips_commands.c:249", "sys/dev/raid/ips/ips_disk.c:139" ], "poc_changes": "n/a - evidence pack authored fresh in this run (harness + build/run scripts); orchestrator seed was only the ips.c reviewers cross-file lead", "attempts": 1, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 25, "guest_dirty": 0, "build_cmd": "sh build.sh (cc -O2 -Wall -o /tmp/flush_invert_harness flush_invert_harness.c)", "run_cmd": "sh run.sh (uname; sysctl debug.ips.ignore_flush_cmd; /tmp/flush_invert_harness as user maxx)", "code_hash": "472efefcff082cd8d3759621c3fab8287d92b2f8017161779f527c970a80eedd", "notes": "impact field reflects kernel-security classes (no corruption/leak/panic); the actual damage is fsync() durability silently broken on default config, Medium per the audit rubric. The ips.c cross-file lead #1 is thereby CONFIRMED. Guest has no ServeRAID hardware (env.txt), so the wire-level command cannot be observed; fix A/B likewise impossible -> fix_status not_testable. Related distinct: DF-4613 (watchdog lock inversion), DF-4614 (queue double-free), DF-4615 (copperhead reinit), DF-4616 (dump poll units).", "recommended_fix": "Invert the condition at ips_commands.c:202 to if (ips_debug_ignore_flush_cmd) so the skip path only runs when the operator explicitly enables it (fix.diff).", "fix_status": "not_testable", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff flips the polarity to match the documented tunable semantics. Baseline inversion reproduced via harness; an end-to-end patched-kernel A/B (observing IPS_CACHE_FLUSH_CMD reach a real adapter) is impossible on the audit guest - QEMU has no ServeRAID device model and the guest has zero 0x1014/0x9005 PCI devices (env.txt). The one-line fix is self-evident against the proven branch.", "fix_evidence": "fix.diff (ips_commands.c:202 !ips_debug_ignore_flush_cmd -> ips_debug_ignore_flush_cmd); run.log baseline harness output" } |