{
  "finding_id": "DF-3078",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "REPRODUCED on stock #0: MNT_RELOAD (mount(2) MNT_UPDATE|MNT_RELOAD|MNT_RDONLY on a RO-mounted UFS) re-reads the superblock and adopts its geometry (ffs_vfsops.c:500) while fs_csp/fs_maxcluster/um_fs keep their mount-time sizes (allocated at :671/:685). Crafted re-read sb gives: heap OOB WRITE with fully attacker-controlled length AND content (cssize variant: 524288 pattern bytes bcopy'd into the 2053-byte fs_csp chunk, reload returned 0, ~522KB heap silently smashed); unbounded OOB write of controlled value (ncg variant: vm_fault stack-guard panic in the *lp++ refill); divide-by-zero (fsize=0: Fatal trap 18 idivl at ffs_mount+0x627); heap OOB READ past um_fs via adopted fs_sbsize at RW-upgrade ff_sbupdate bcopy (sbsize=65536: Fatal trap 12 supervisor-read in memmove; sbsize=8192: the 6144 bytes beyond um_fs written to the raw media). Adoption in returning reloads proven via crafted fs_dsize showing in df. NOT an unpriv->root LPE: trigger is root-gated (get_fscap maps ufs to SYSCAP_RESTRICTEDROOT; vfs.usermount=1 does not help — same blocker empirically proven in the DF-0820 pack). Impact ceiling: root-context kernel heap corruption + kernel-heap disclosure to media; panic DoS demonstrated.",
  "exploit_chain": "",
  "evidence": [
    "findings/poc/DF-3078/run.log — full baseline transcript (all variants)",
    "findings/poc/DF-3078/panic_idivl_fsize0.txt — Fatal trap 18 idivl (fsize=0 adopted)",
    "findings/poc/DF-3078/panic_maxcluster_ncg.txt — vm_fault stack-guard panic (ncg=0x20000000 refill store)",
    "findings/poc/DF-3078/panic_sbupdate_oob_read.txt — trap 12 supervisor READ in memmove (sbsize=65536 sbupdate OOB read)",
    "findings/poc/DF-3078/run.patched.log — fix validation: all crafted variants EINVAL on #1, regressions pass",
    "findings/poc/DF-3078/build.log, env.txt, fix.diff"
  ],
  "kernel_refs": [
    "sys/vfs/ufs/ffs_vfsops.c:479",
    "sys/vfs/ufs/ffs_vfsops.c:484",
    "sys/vfs/ufs/ffs_vfsops.c:493",
    "sys/vfs/ufs/ffs_vfsops.c:495",
    "sys/vfs/ufs/ffs_vfsops.c:500",
    "sys/vfs/ufs/ffs_vfsops.c:515",
    "sys/vfs/ufs/ffs_vfsops.c:526",
    "sys/vfs/ufs/ffs_vfsops.c:536",
    "sys/vfs/ufs/ffs_vfsops.c:671",
    "sys/vfs/ufs/ffs_vfsops.c:685",
    "sys/vfs/ufs/ffs_vfsops.c:1292",
    "sys/vfs/ufs/ffs_vfsops.c:1295"
  ],
  "poc_changes": "Trigger written from scratch: DF's mount_ufs has no '-o reload' option, so the PoC calls mount(2) directly with MNT_UPDATE|MNT_RELOAD|MNT_RDONLY and a zeroed >=sizeof(struct ufs_args) data buffer (a first draft passed a too-small struct and would have made ffs_mount's copyin over-read user memory). craft.c/dumpsb.c built on-guest with -I/usr/src; sb field offsets verified in-guest (fs_cssize=156, fs_fsize=52, fs_ncg=44, fs_sbsize=104, fs_dsize=40, fs_fmod=208).",
  "attempts": 9,
  "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": 3300,
  "guest_dirty": 0,
  "build_cmd": "cd /root/rt && cc -o craft craft.c && cc -I/usr/src -o dumpsb dumpsb.c && cc -o reload reload.c",
  "run_cmd": "sh run.sh <unchanged|cssize|fsize0|ncg|sbsize_leak|sbsize_fault>   (guest root; see README)",
  "code_hash": "8c248f01eaf8720192f80f1e6c4f974de69a358aac79d064cbcbe6a193c73854",
  "notes": "Related: DF-0820 (initial-mount geometry census — NOT re-filed; different function/root-cause), DF-3047 (ext2 MNT_RELOAD analog), DF-3015 (maxsymlinklen trust boundary gains a second import path at :504). fs_fmod adoption alone is NOT a reachable rofs-mod panic: sys_sync's callback (vfs_syscalls.c:1199) and the syncer (vfs_sync.c:731) both skip RDONLY mounts — killed empirically (95+ s with fs_fmod=1 adopted, 60 sync()s, no panic). Guest reset clean (vm.sh reset with-src) after validation.",
  "recommended_fix": "ffs_reload: reject any re-read superblock whose sizing geometry differs from the mounted one (fs_sbsize/bsize/fsize/frag/ncg/ipg/cssize/csaddr/contigsumsize/bshift/fshift) with EINVAL, and force fs_fmod=0 — see fix.diff; validated on a single-fix kernel.",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly 6.5-DEVELOPMENT #1: Sun Sep  6 02:02:00 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff applied to in-guest /usr/src, make -j6 nativekernel KERNCONF=X86_64_GENERIC + installkernel (BUILD_OK), rebooted into #1: all five crafted variants now return 'mount: Invalid argument' (EINVAL) with the guest staying up and the filesystem still accessible; unchanged-sb reload returns 0; fresh RW mount + file create works. Before/after matrix in VERDICT.md and run.patched.log.",
  "fix_evidence": [
    "findings/poc/DF-3078/run.patched.log",
    "findings/poc/DF-3078/build.log",
    "findings/poc/DF-3078/fix.diff"
  ]
}
