DIOCRECLUSTER has no privilege check and the kernel services dmsg peers with root credentials (raw RW with proc0.p_ucred, no open/keyid validation on I/O) β gated today only by diskopen's SYSCAP_RESTRICTEDROOT
| Field | Value |
|---|---|
| ID | DF-2874 |
| Status | new |
| Severity | Info |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:L/I:L/A:N |
| CWE | CWE-862 Missing Authorization |
| File | sys/kern/subr_diskiocom.c |
| Lines | 108-130 (root open :281-282; gate subr_disk.c:78-80) |
| Area | kern |
| Confidence | certain |
| Discovered | 2026-09-02 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | base:kern |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
diskioctl forwards DIOCRECLUSTER with no priv_check and no FWRITE-on-node requirement; holdfp accepts any fd; disk_blk_open then does dev_dopen(rawdev, FREAD|FWRITE, SIFCHR, proc0.p_ucred) β the kernel opens the raw disk READ-WRITE with root credentials at the message peer's request β and the read/write/flush/freeblks handlers perform raw I/O with no BLK_OPEN/keyid validation. On this system the unprivileged chain is blocked because diskopen enforces SYSCAP_RESTRICTEDROOT on every disk-volume open (verified EPERM for operator-group) β filed as defense-in-depth: the entire dmsg peer trust model hangs on that one incidental gate. PoC verified the peer-position chain on stock (kernel opened the mounted raw boot disk RW; 4KB write landed on raw disk, md5-verified); unprivileged claim honestly not reproduced. Fix: explicit FWRITE gate on DIOCRECLUSTER.
Recommended fix
Validated fix.diff in findings/poc/DF-2874/.
Timeline
- 2026-09-02 Discovered during pass-2 audit of subr_diskiocom.c (GLM 5.3); peer chain reproduced + fix validated same run.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2874 Β· 12 files| File | Type | Description | Size | |
|---|---|---|---|---|
| dfpeer.c | β | 15.4 KB | view raw | |
| run_f1.sh | β | 1.8 KB | view raw | |
| run_f1b.sh | β | 932 B | view raw | |
| run.log | β | 1.6 KB | view raw | |
| fix.diff | β | 664 B | view raw | |
| build.sh | β | 51 B | view raw | |
| run.sh | β | 391 B | view raw | |
| env.txt | β | 373 B | view raw | |
| VERDICT.md | β | 2.2 KB | β raw | |
| run.fix.log | β | 456 B | view raw | |
| verdict.json | β | 2.7 KB | view raw | |
| README.md | β | 1.8 KB | β raw |
DF-2874 β DIOCRECLUSTER: no privilege check; kernel opens the raw disk
FREAD|FWRITE with proc0.p_ucred on the dmsg peer's request (Info β
mitigated by diskopen's SYSCAP_RESTRICTEDROOT gate)
What this pack contains
dfpeer.cβ dmsg wire peer;openwrmode issues BLK_OPEN(RD|WR) and prints the kernel's reply (error=0= dev_dopen(rawdev, FREAD|FWRITE, S_IFCHR, proc0.p_ucred, ...) succeeded).run_f1.shβ full chain attempt as an unprivileged operator-group user.run_f1b.shβ the chain at the dmsg-peer position (root harness): BLK_OPEN(RD|WR) β raw write through the channel β root dd readback shows the payload on the raw disk.
Outcome
- Peer position (verified):
BLK_OPEN modes=3 -> reply error=0; a 4KB 0x5a write at gap offset 0x77F000000 lands on the raw disk (confirmed by root dd md5) and reads back through the channel. - Unprivileged position (blocked): a member of group operator cannot
even open /dev/vbd0 read-only β
diskopen()(sys/kern/subr_disk.c:78-80) enforcescaps_priv_check_self(SYSCAP_RESTRICTEDROOT)on every disk volume open, so the ioctl path is effectively root-only on this system. The missingpriv_checkindiskioctl()/disk_iocom_ioctl()is therefore a defense-in-depth gap (the 0640 root:operator node perms and the absence of any FWRITE-on-node requirement would otherwise let an operator-group user turn read-only device access into kernel-mediated root-credential raw disk R/W). - Also demonstrated:
disk_blk_write/disk_blk_readperform raw I/O with no BLK_OPEN/keyid validation at all β every message the iocom receives is executed with root credentials.
fix.diff
Require FWRITE on the device node for DIOCRECLUSTER (devfs then enforces write permission at open time), making the gate explicit instead of incidental.
DF-2874 VERDICT
Status: not_reproduced for the unprivileged-escalation claim
(blocked by an external gate); the root-credential proxy behavior
itself is verified at the peer position.
Guest: DragonFly 6.5-DEVELOPMENT X86_64_GENERIC (env.txt).
What was verified
- Peer position (root harness == stand-in for a routed cluster
node):
BLK_OPEN modes=3 β reply error=0, i.e.dev_dopen(dp->d_rawdev, FREAD|FWRITE, S_IFCHR, proc0.p_ucred, NULL, NULL)(sys/kern/subr_diskiocom.c:281-282) succeeded β the kernel opened the raw boot disk READ-WRITE with root credentials on the message peer's request, even though the device node perms are 0640 root:operator (no write for group) and the fs is mounted. A 4KB write through the channel landed on the raw disk (root dd md5-verified) and read back through the channel. - No open validation for I/O:
disk_blk_write/disk_blk_read/_flush/_freeblksnever check that a BLK_OPEN happened or validate keyid β every message the iocom receives executes raw I/O with root credentials. - Unprivileged chain (blocked): user
poc(member of group operator) cannot open /dev/vbd0 even read-only:diskopen()enforcescaps_priv_check_self(SYSCAP_RESTRICTEDROOT)(sys/kern/subr_disk.c:78-80) on every disk-volume open, returning EPERM before the DIOCRECLUSTER branch in diskioctl is reachable. Therefore the missingpriv_check/FWRITE requirement indiskioctl(subr_disk.c:1191) /disk_iocom_ioctl(subr_diskiocom.c:108-130) is currently mitigated by that gate. Had the gate not been there, 0640 root:operator + O_RDONLY would have been sufficient for operatorβroot-equivalent raw disk R/W.
Why filed as Info
The kernel-side authorization gap is real (no priv_check, arbitrary fd types accepted via holdfp, proc0.p_ucred raw opens, no peer revalidation), but on this system it is unreachable for unprivileged users. Defense-in-depth recommendation: require FWRITE on the node (devfs then enforces write permission) β fix.diff does exactly that.
Fix validation
fix.diff (FWRITE required for DIOCRECLUSTER) applied, kernel rebuilt:
openwr via an O_RDONLY fd returns EPERM; via O_RDWR (root) still
works (run.fix.log).
Fix verification
fixedFix kernel: DIOCRECLUSTER via O_RDONLY fd returns EPERM; via O_RDWR (root) still works. Gate explicit.
['run.fix.log']
Confirmed kernel references
Detail
Evidence (decisive lines)
['run.log (BLK_OPEN modes=3 -> error=0; raw write md5-verified on disk; unpriv open EPERM)', 'VERDICT.md', 'run.fix.log (fixed: O_RDONLY ioctl -> EPERM, O_RDWR works)']
PoC changes
No seed; wrote dfpeer.c (openwr/write/read modes) plus the operator-user orchestration run_f1.sh/run_f1b.sh
Verified recommended fix
Require FWRITE on the device node for DIOCRECLUSTER so the gate is explicit (devfs then enforces write permission at open)
Verdict
The authorization gap is real at the kernel-service level - DIOCRECLUSTER has no priv_check and accepts any fd; BLK_OPEN then does dev_dopen(rawdev, FREAD|FWRITE, S_IFCHR, proc0.p_ucred, ...) (subr_diskiocom.c:281) and BLK_WRITE/READ/FLUSH/FREEBLKS execute raw I/O with zero open/keyid validation - and the peer-position chain was verified (BLK_OPEN error=0; a write through the channel landed on the raw boot disk and was md5-verified by root dd). BUT the unprivileged claim does not reproduce on this system: diskopen() gates every disk-volume open with caps_priv_check_self(SYSCAP_RESTRICTEDROOT) (subr_disk.c:78-80), so an operator-group user cannot even open /dev/vbd0 O_RDONLY (EPERM) and never reaches the ioctl. Filed as Info/defense-in-depth: had the gate not been there, 0640 root:operator + O_RDONLY would have sufficed for operator->root-equivalent raw disk R/W.
No comments yet.