⬢ DragonFlyBSD Kernel Audit
DF-4639 / verdict.json
← back to finding ↓ download raw
{
  "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"
}