DF-4758 / verdict.json
{ "finding_id": "DF-4758", "status": "reproduced", "reproduced": 1, "impact": "dos", "confidence": "certain", "verdict": "vinumsize() (sys/dev/raid/vinum/vinum.c:564) indexes the volume array with Volno(dev) with no DEVTYPE dispatch and no bounds check; raw sd/plex minors encode the subdisk/plex number in the bits Volno() extracts, so d_psize on /dev/vinum/sd/sN reads VOL[N]. Reproduced on the stock-kernel guest: swapon /dev/vinum/sd/s0 (a 1 MB subdisk) installed 12288 512-blocks of swap -- exactly volume v0s 6 MB size -- proving the wrong-object lookup deterministically; s4/s5 executed OOB reads past the 4-entry VOL array (heap-dependent ENXIO on this boot). Impact ceiling: swap sized from the wrong object -> swap I/O beyond the subdisk extent (silent disk/data corruption, garbage swap-in), plus heap OOB read. Root-gated (swapon SYSCAP_RESTRICTEDROOT).", "exploit_chain": "", "evidence": "findings/poc/DF-4758/df4758_run2.log: swapon(/dev/vinum/sd/s0): OK followed by swapinfo /dev/vinum/sd/s0 12288 (volume size on a subdisk); fix_run.log: patched module rejects all sd swapons (ENXIO) while /dev/vinum/vol/v0 still installs the correct 12288 blocks", "kernel_refs": [ "sys/dev/raid/vinum/vinum.c:564", "sys/dev/raid/vinum/vinum.c:58-70", "sys/dev/raid/vinum/vinumutil.c:239-243", "sys/dev/raid/vinum/vinumvar.h:124-132", "sys/vm/vm_swap.c:296-348" ], "poc_changes": "seed had none; wrote df4758_swapon.c (swapon(2) per device path with exact errno + swapinfo) and run.sh/run2.sh; first build failed on a nonexistent sys/swapon.h include (removed; swapon lives in unistd.h), second build clean", "attempts": 2, "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", "runtime_sec": 95, "guest_dirty": 0, "build_cmd": "cc -O -o /tmp/df4758_swapon /tmp/df4758_swapon.c", "run_cmd": "kldload vinum; sh /tmp/df4758_run.sh; sh /tmp/df4758_run2.sh (= ./df4758_swapon /dev/vinum/sd/s0 /dev/vinum/sd/s1 /dev/vinum/sd/s4 /dev/vinum/sd/s5; swapinfo)", "code_hash": "4081874cf0e1fe06fb5acb942013489a74e0d36d39f446834254f2b73827efba", "notes": "OOB probes (s4/s5) returned ENXIO on this boot -- the OOB read executes but its observable result depends on heap contents; the in-bounds s0 result proves the wrong-object indexing deterministically. swapon root-only; vinum config created as root on /dev/md0s0a using findings/poc/DF-4592/label.bin.", "recommended_fix": "vinumsize(): dispatch on DEVTYPE(dev) == VINUM_VOLUME_TYPE and bounds-check Volno(dev) against vinum_conf.volumes_allocated before touching VOL[] (see fix.diff)", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "vinum.ko rebuilt from patched /usr/src on the guest (make rc=0), installed, loaded: swapon on every sd device now ENXIO with swapinfo clean (baseline: s0 OK with bogus 12288-block install), and the positive control /dev/vinum/vol/v0 still installs the correct 12288-block size. Bad behavior gone.", "fix_evidence": "findings/poc/DF-4758/fix_run.log (patched run + baseline comparison + positive control); fix.diff in the same pack" } |