{
  "finding_id": "DF-2831",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "REPRODUCED. dssize() (subr_diskslice.c:849-870) walks dp->d_slice and its per-slice disklabel with no ds_token while disk_msg_core's forced reprobes replace and dsgone() those structures; diskpsize() (subr_disk.c:1259-1276) is its only caller and also takes no token. On the stock INVARIANTS guest, swapon on vn0s1a racing root-forced DIOCSYNCSLICEINFO reprobes silently installed whole-disk-sized swap (16384 blocks) for a 4096-block partition in 6-14% of 2000-cycle runs (4 independent runs, one from a fresh vm.sh reset), while a same-instant DIOCGDINFO64 probe proved the in-core label was correct - the value came from state outside the label. With kprintf tracing between the racy reads the same race produced a fatal trap 12 page fault in dssize+0x15c (movq 0x40(%rax),%rax, fault addr 0x40) with the serial trace showing ENTER ssp=...7c00 vs WALK ssp=...6a00 - dssize dereferencing a freed previous-generation struct diskslices; guest died at db> (panic.txt). Provenance of the silent wrong value was then pinned 1:1 (219/219): reprobe label re-reads fail through the unserialized diskstrategy (DF-2742 family) causing disk_probe_slice to clear the slice label, dssize returns -1, and diskpsize's DSO_RAWPSIZE fallback substitutes the raw whole-disk size for a PARTITION device. Privileged trigger (root races root / forced reprobe vs automated swap management); impact ceiling: UAF read (panic), silent wrong swap geometry (oversized swap on a partition, swap accounting corruption). Fix (ds_token around dssize in diskpsize + slice-bounds revalidation in dssize/dsopen + RAWPSIZE fallback restricted to whole-disk/whole-slice devices) validated on rebuilt kernel #3: wrong-size 0/2000 and 0/2000 vs 125-277 stock, failures become clean ENXIO, control run 2000/2000 OK, no panic, guest stable.",
  "exploit_chain": "root: hammer ioctl(DIOCSYNCSLICEINFO,1) on a disk with an open slice partition; concurrently swapon() that partition -> dev_dpsize -> diskpsize -> dssize snapshots *sspp, reopens (mask gone after reprobe), reloads ssp, dereferences dss_slices[slice].ds_label/.ds_ops while the reprobe's dsgone() freed them -> UAF read (fatal trap 12 observed instrumented) or, via label-clear + DSO_RAWPSIZE fallback, silent whole-disk-sized swap installed on a partition (integrity/DoS). No unpriv->root chain: both triggers are privileged (SYSCAP_RESTRICTEDROOT on open).",
  "evidence": [
    "findings/poc/DF-2831/run.log: stock counters 206/285/244/277/125 wrong-size of 2000/2000/1500/2000/2000, control 0",
    "findings/poc/DF-2831/panic.txt: DF2831 ENTER ssp=0xfffff8008d5d7c00 vs WALK ssp=0xfffff8008d5d6a00 then 'Fatal trap 12 ... Stopped at dssize+0x15c: movq 0x40(%rax),%rax'",
    "findings/poc/DF-2831/VERDICT.md: fix+instrumentation trace 219x 'blocks=-1 nolabel' == 219x 'RAWPSIZE fallback -> raw whole-disk size' (provenance)",
    "findings/poc/DF-2831/fix_run.log: fix kernel #3 ok_WRONG_SIZE=0 twice, swapon_err 703/887 clean ENXIO, no-hammer 2000/2000, guest up"
  ],
  "kernel_refs": [
    "sys/kern/subr_diskslice.c:849-870",
    "sys/kern/subr_diskslice.c:761-777",
    "sys/kern/subr_disk.c:1259-1276",
    "sys/kern/subr_disk.c:1270-1274",
    "sys/kern/subr_disk.c:367-368",
    "sys/kern/subr_disk.c:494",
    "sys/vm/vm_swap.c:307-317",
    "sys/dev/disk/vn/vn.c:579"
  ],
  "poc_changes": "Wrote PoC from scratch (no seed): genimg2831.c builds an MBR+DFLYBSD-slice+valid-disklabel64 image with a 2MiB FS_SWAP partition 'a' (fstype must be non-zero or devfs creates no s1a node); poc2831.c errno-class racer; poc2831b.c size-checking racer with same-instant DIOCGDINFO64 in-core label probe and dual-disk churn variant; instrument.diff/fixinst.diff for kernel provenance tracing.",
  "attempts": 9,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 (stock baseline; instrumented #1 / fix+inst #2 / final fix #3 built in-guest)",
  "runtime_sec": 9600,
  "guest_dirty": 1,
  "build_cmd": "cc -O -o genimg2831 genimg2831.c && cc -O -o poc2831 poc2831.c -lpthread && cc -O -o poc2831b poc2831b.c -lpthread && ./genimg2831 /root/df2831/df2831.img 2097152",
  "run_cmd": "./poc2831b /dev/vn0 /dev/vn0s1a /dev/vn1 /dev/vn1s1a 2000 0   (plus ./poc2831 /dev/vn0 /dev/vn0s1a 2000 0 control)",
  "code_hash": "34694594fd832626d6e2c79c129130a7145b89383051e895f1320c219357b140",
  "notes": "Sibling of DF-2742 (diskstrategy) - distinct sink (d_psize/dssize) needing its own fix site; DF-2742's recommended fix does not cover it. Transient label loss feeding the RAWPSIZE path is the DF-2742 family upstream; residual clean ENXIO failures under race disappear if DF-2742 is also fixed. Not re-reported here: DF-0074/0075 (DIOCGSLICEINFO), DF-2741 (bcopy sink), DF-2663 (clamp consumer), DF-0134 (label64 media validation gap - the dscheck hostile-offset arithmetic in this file is that finding's consumer; recommend upgrading DF-0134 impact since dscheck :280 turns unvalidated p_boffset into an arbitrary absolute bio_offset incl. 64-bit wrap to negative off_t, vn/nvme pass it through unbounded).",
  "recommended_fix": "Take ds_token around the dssize() call in diskpsize(), revalidate slice < dss_nslices after dssize's re-open reload (and add the same bounds check to dsopen), and restrict the DSO_RAWPSIZE fallback to whole-disk/whole-slice devices so partition geometry is never silently replaced by whole-disk size - see fix.diff.",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly 6.5-DEVELOPMENT #3: Tue Sep  1 23:37:41 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 guest /usr/src, make nativekernel + installkernel, reboot into #3. Baseline (stock, fresh reset): ok_WRONG_SIZE 277/2000 and 125/2000, silent. Patched: ok_WRONG_SIZE 0/2000 and 0/2000, swapon failures under race became clean ENXIO (703/887) instead of a silent 4x-oversized swap device; control (no hammer) 2000/2000 OK; no panic; guest stable. UAF walk eliminated (token-serialized build ran equal churn with zero faults vs stock-instrumented fatal trap 12 within 800 iterations).",
  "fix_evidence": "findings/poc/DF-2831/fix_run.log; findings/poc/DF-2831/fix.diff; VERDICT.md 'Fix validation'"
}
