l64_setdisklabel accepts internally inconsistent label geometry: d_pbase/d_pstop/d_bbase unvalidated, partitions may overlap the label+boot area, and d_bbase directly becomes ds_reserved (0 disables the label-area EROFS guard)
| Field | Value |
|---|---|
| ID | DF-2911 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:L/A:L |
| CWE | CWE-20 / CWE-1287 |
| File | sys/kern/subr_disklabel64.c |
| Lines | 278-306 (esp. :302), 526 |
| Area | kern/disk |
| 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
Beyond the known DF-0135 wraparound, l64_setdisklabel's sanity block never bounds d_bbase or d_pstop, never requires d_pbase <= d_total_size, and never requires partitions to start at/after d_bbase β so an installed label may (a) define partitions overlapping the label and boot area (only p_boffset >= d_pbase is enforced, and d_pbase itself may be 0), and (b) carry an arbitrary d_bbase which l64_adjust_label_reserved converts directly into sp->ds_reserved: d_bbase=0 disables the EROFS label-area protection for that slice, while a huge d_bbase makes the whole slice read-only (EROFS DoS). Reachable via DIOCSDINFO64/DIOCWDINFO64 which require FWRITE on the slice device (root/operator) β consistency/self-inflicted rather than a privilege boundary. Fix: validate d_bbase <= d_total_size, d_pbase >= d_bbase, d_pbase <= d_pstop <= d_total_size, and change the partition lower bound from d_pbase to d_bbase.
Timeline
- 2026-09-02 Discovered during pass-2 audit of subr_disklabel64.c (GLM 5.3).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2911 Β· 10 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 739 B | β raw | |
| VERDICT.md | β | 2.1 KB | β raw | |
| build.sh | β | 65 B | view raw | |
| df2911_lab64.c | β | 2.9 KB | view raw | |
| df2911_run.log | β | 515 B | view raw | |
| env.txt | β | 401 B | view raw | |
| fix.diff | β | 759 B | view raw | |
| manifest.json | β | 739 B | view raw | |
| run.sh | β | 122 B | view raw | |
| verdict.json | β | 2.2 KB | view raw |
DF-2911 PoC evidence pack
What
l64_setdisklabel accepts inconsistent geometry: d_bbase=0 disables the EROFS label-area guard; huge d_bbase locks the slice.
Build
cc -o df2911 df2911_lab64.c -lz
Run
vnconfig + fdisk -IB + disklabel64 -w, then ./df2911 /dev/vn0s1
Expected
control pwrite EROFS; after d_bbase=0 label: pwrite=512 (label area writable); after d_bbase=pstop: EROFS everywhere
Guest: DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:04 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64 All logs are full untrimmed captures unless noted. fix.diff is the git-apply-able verified fix (authored after verification; never applied to the audit tree).
DF-2911 - verification verdict
Status: reproduced | reproduced: 1 | impact: denial_of_service | confidence: certain
Both directions reproduced live on a vn-backed scratch disk with DIOCSDINFO64. Control: with the stock label (d_bbase=4096) a pwrite at slice offset 0 returns EROFS (the ds_reserved label-area guard, subr_diskslice.c:227). (a) A label with d_bbase=0 (CRC recomputed) is ACCEPTED by l64_setdisklabel - no check bounds d_bbase - and the same pwrite then returns 512: the EROFS label-area protection is fully disabled and we overwrote the on-disk label area. (b) A label with d_bbase=d_pstop=1072676864 (whole slice reserved, unvalidated) is ACCEPTED and every write to the slice returns EROFS - whole-slice lockout via one label ioctl. FWRITE root/operator-gated; consistency/self-inflicted class, not a privilege boundary.
Evidence pointers
df2911_run.log: control EROFS; bbase=0 accepted then pwrite=512 WRITE ACCEPTED BELOW LABEL; bbase=pstop accepted then EROFS everywhere
Kernel references
- sys/kern/subr_disklabel64.c:278
- sys/kern/subr_disklabel64.c:296
- sys/kern/subr_disklabel64.c:526
- sys/kern/subr_diskslice.c:227
PoC changes vs the filing sketch
had to recompute the label d_crc (crc32 over d_magic..d_partitions[n]) after editing - the kernel validates it before the sanity block
Fix
recommendation: validate d_bbase <= d_total_size, d_pbase >= d_bbase, d_pbase <= d_pstop <= d_total_size, partition lower bound d_bbase
fix status: not_testable
fix compiled in fix-all kernel; label-rig A/B rerun not performed (kernel build time-boxed); the fixed validation rejects both crafted labels by construction
Guest: DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:04 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64
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_testablefix compiled in fix-all kernel; label-rig A/B rerun not performed (kernel build time-boxed); the fixed validation rejects both crafted labels by construction
Confirmed kernel references
Detail
Evidence (decisive lines)
df2911_run.log: control EROFS; bbase=0 accepted then pwrite=512 WRITE ACCEPTED BELOW LABEL; bbase=pstop accepted then EROFS everywhere
PoC changes
had to recompute the label d_crc (crc32 over d_magic..d_partitions[n]) after editing - the kernel validates it before the sanity block
Verified recommended fix
validate d_bbase <= d_total_size, d_pbase >= d_bbase, d_pbase <= d_pstop <= d_total_size, partition lower bound d_bbase
Verdict
Both directions reproduced live on a vn-backed scratch disk with DIOCSDINFO64. Control: with the stock label (d_bbase=4096) a pwrite at slice offset 0 returns EROFS (the ds_reserved label-area guard, subr_diskslice.c:227). (a) A label with d_bbase=0 (CRC recomputed) is ACCEPTED by l64_setdisklabel - no check bounds d_bbase - and the same pwrite then returns 512: the EROFS label-area protection is fully disabled and we overwrote the on-disk label area. (b) A label with d_bbase=d_pstop=1072676864 (whole slice reserved, unvalidated) is ACCEPTED and every write to the slice returns EROFS - whole-slice lockout via one label ioctl. FWRITE root/operator-gated; consistency/self-inflicted class, not a privilege boundary.
No comments yet.