Modifying ioctls (MPTIO_WRITE_CFG_PAGE MPTIO_RAID_ACTION) allowed via read-only file descriptor
Summary
mpt character device created mode 0640 (operator group read-only) but mpt_ioctl performs no FWRITE check before dispatching state-changing ioctls MPTIO_WRITE_CFG_PAGE and MPTIO_RAID_ACTION. Operator-group user who can only open node O_RDONLY can rewrite controller config pages and issue RAID actions including volume deletion bypassing write-permission boundary implied by 0640 mode. DragonFly imposes no framework-level requirement fd opened FWRITE to issue ioctl so driver is sole enforcer. [VERIFIED pass2: HW-gated no MPT on guest - source-certain no FWRITE check on mutating MPTIO ioctls over 0640 GID_OPERATOR node; fflag fix compile-validated building full mpt.ko -Werror]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2487 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 901 B | β raw | |
| VERDICT.md | β | 2.1 KB | β raw | |
| build.sh | β | 99 B | view raw | |
| run.log | β | 404 B | view raw | |
| env.txt | β | 963 B | view raw | |
| fix.diff | β | 909 B | view raw | |
| manifest.json | β | 681 B | view raw | |
| verdict.json | β | 2.5 KB | view raw |
DF-2487 -- mpt modifying ioctls allowed via read-only fd
Verification used the shared rig tree at /root/rigs on the audit guest (see manifest). The rig for this finding: dfv_mpt (rig.c = harness, gen.sh = verbatim extractor, dfv_*_extract.h = generated production text). The decisive outputs below were captured live on the guest during the 2026-10-24 verification session; full session logs are summarized per run.
Build
sh build.sh # extracts verbatim driver text + builds the KLD
Run (guest, root)
kldload ./dfv_rig.ko
(compile validation only - no MPT hardware on the guest)
Expected
mpt.ko built clean with the fix (compile validation); source trace of both dispatch sites.
Fix validation
fix.diff adds FWRITE checks to MPTIO_WRITE_CFG_PAGE and MPTIO_RAID_ACTION; module builds clean.
Verdict: not_reproduced / impact=none (see verdict.json, VERDICT.md)
DF-2487 verdict -- mpt modifying ioctls allowed via read-only fd
status: not_reproduced reproduced: 0 impact: none confidence: certain attempts: 2 runtime_sec: 300
HW-gated at runtime: the mpt character device is created only when an LSI MPT HBA attaches (mpt_user.c:116 inside the attach path); the guest has no MPT controller (pciconf -l shows PIIX3 IDE + virtio only, camcontrol shows the QEMU DVD only), so /dev/mptN does not exist and the ioctl path is dead here. The defect is source-certain: mpt_ioctl dispatches MPTIO_WRITE_CFG_PAGE (mpt_user.c:715) and MPTIO_RAID_ACTION (:729) - both state-mutating, including volume deletion - with no check that the fd was opened FWRITE, while the node is created 0640 GID_OPERATOR (operator can open O_RDONLY). The fix adds a_fflag & FWRITE gates to both cases; validated by building the complete mpt.ko module (all six objects, -Werror) against the patched tree - the first compile round correctly caught the wrong field name (a_oflags -> a_fflag) and a missing fcntl.h include, proving the validation path exercises the real driver.
Evidence (decisive lines)
$ cd /usr/src/sys/dev/disk/mpt && make -m /usr/src/share/mk all
round 1 (initial fix draft): error: struct dev_ioctl_args has no member a_oflags; FWRITE undeclared
-> corrected to a_fflag + #include
Exploit chain / privesc assessment
privileged-boundary bypass for the operator group on machines with MPT hardware; not reachable on this guest.
Fix + A/B
fix.diff adds FWRITE checks to MPTIO_WRITE_CFG_PAGE and MPTIO_RAID_ACTION; module builds clean.
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
not_testableConfirmed kernel references
Detail
Exploit chain
privileged-boundary bypass for the operator group on machines with MPT hardware; not reachable on this guest.
Evidence (decisive lines)
mpt.ko built clean with the fix (compile validation); source trace of both dispatch sites.
PoC changes
no rig - compile validation against the real module build.
Verified recommended fix
require FWRITE on the fd for MPTIO_WRITE_CFG_PAGE and MPTIO_RAID_ACTION
Verdict
HW-gated at runtime: the mpt character device is created only when an LSI MPT HBA attaches (mpt_user.c:116 inside the attach path); the guest has no MPT controller (pciconf -l shows PIIX3 IDE + virtio only, camcontrol shows the QEMU DVD only), so /dev/mptN does not exist and the ioctl path is dead here. The defect is source-certain: mpt_ioctl dispatches MPTIO_WRITE_CFG_PAGE (mpt_user.c:715) and MPTIO_RAID_ACTION (:729) - both state-mutating, including volume deletion - with no check that the fd was opened FWRITE, while the node is created 0640 GID_OPERATOR (operator can open O_RDONLY). The fix adds a_fflag & FWRITE gates to both cases; validated by building the complete mpt.ko module (all six objects, -Werror) against the patched tree - the first compile round correctly caught the wrong field name (a_oflags -> a_fflag) and a missing fcntl.h include, proving the validation path exercises the real driver.
No comments yet.