FFS allocator uses unvalidated on-disk cylinder-group header fields as kernel-memory offsets/indexes β crafted image gives attacker-offset OOB read/write on first allocation
| Field | Value |
|---|---|
| ID | DF-3035 |
| Status | new |
| Severity | High |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:C/C:L/I:H/A:H |
| CWE | CWE-787 / CWE-125 / CWE-20 |
| File | sys/vfs/ufs/ffs_alloc.c |
| Lines | 1010, 1128-1218, 1294, 1370, 1383-1463, 1532-1609, 1836, 1893-1963 |
| Area | vfs/ufs |
| Confidence | certain |
| Discovered | 2026-09-02 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | memcorrupt |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
Every cg consumer in ffs_alloc.c reads the on-disk cg block with bread(), applies only cg_chkmagic() (a magic comparison), then uses raw on-disk fields as pointer offsets and array indexes into kernel memory: cg_cgx β fs->fs_csp[16Β·cg_cgx].cs_nbfreeββ and fs->fs_maxcluster[4Β·cg_cgx] stores (signed 32-bit index β Β±8/Β±32 GiB around heap objects); cg_freeoff/cg_iusedoff/cg_boff/cg_btotoff/ cg_clustersumoff/cg_clusteroff β bit/int16/int32 read-modify-write through cgbuf+offset (Β±2 GiB); cg_rotor/cg_frotor/cg_irotor/ cg_nclusterblks β OOB scan bounds; plus inode-content-derived bpref β dtog() β fs_csp[] OOB read before bread. Mount validates none of it (ffs_vfsops checks only fs_magic/fs_bsize). Distinct validation surface from DF-0820 (superblock) and DF-0794 (fs_ncg). Crafted FFS media mounted by root (DF-0820/DF-3015 model) with a single creat/write as the poisoned first allocation: arbitrary-offset relative kernel-memory corruption (silent int32 inc/dec/store and bit writes when the offset lands on mapped pages, fatal trap when it doesn't) and reliable local DoS; on vfs.usermount=1 or auto-mounted-media setups the corruption itself is unprivileged. VERIFIED (stock INVARIANTS, DF-3015 harness): cg_cgx=0x40000000 β deterministic Fatal trap 12 supervisor WRITE at ffs_clusteracct (the fs_maxcluster[cg_cgx] store at base+4Β·index, 3 boots); cg_iusedoff=0x20000000 β Fatal trap 12 supervisor READ at ffs_nodealloccg (inosused[ipref] read at cgbuf+512MiB); control image allocates cleanly. userβroot: N/A on default configs (mount requires root); primitive characterized as attacker-offset Β±8..32GiB relative write + bit-level writes β escalation chain only meaningful under usermount, where it is direct kernel R/W. Fix validated in-guest (ffs_chkcg validation at every cg consumer + bprefβcg clamp): both poisoned images now fail gracefully ENOSPC, control image still allocates cleanly.
Timeline
- 2026-09-02 Discovered during pass-2 audit of ffs_alloc.c (GLM 5.3); deterministic crafted-image kernel R/W faults reproduced + fix validated. DF-0793/0794 re-verified, not re-reported.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3035 Β· 18 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 5.3 KB | β raw | |
| VERDICT.md | β | 6.4 KB | β raw | |
| cgxtool.c | β | 3.9 KB | view raw | |
| setup3035.sh | β | 1.3 KB | view raw | |
| fs.h | β | 24.2 KB | view raw | |
| dinode.h | β | 5.6 KB | view raw | |
| fix.diff | β | 4.2 KB | view raw | |
| build.log | β | 1.9 KB | view raw | |
| run.log | β | 4.0 KB | view raw | |
| run.setup.log | β | 1.1 KB | view raw | |
| run.patched.log | β | 878 B | view raw | |
| panic1.txt | β | 687 B | view raw | |
| panic2.txt | β | 686 B | view raw | |
| panic3.txt | β | 686 B | view raw | |
| panic4.txt | β | 677 B | view raw | |
| env.txt | β | 709 B | view raw | |
| manifest.json | β | 2.0 KB | view raw | |
| verdict.json | β | 8.7 KB | view raw |
DF-3035 β FFS allocator trusts unvalidated on-disk cylinder-group headers
(sys/vfs/ufs/ffs_alloc.c) β attacker-offset OOB kernel read/write on a
crafted filesystem image
What
Every allocator in sys/vfs/ufs/ffs_alloc.c reads a cylinder-group block
with bread(), applies only cg_chkmagic() β a magic comparison
(sys/vfs/ufs/fs.h:398) β and then uses raw on-disk cg-header fields as
byte offsets into the cg buffer and array indexes into kernel memory:
| on-disk field | sink in ffs_alloc.c | primitive |
|---|---|---|
cg_cgx |
fs->fs_cs(fs, cgp->cg_cgx).cs_nbfree-- β ffs_alloccgblk:1213; fs->fs_maxcluster[cgp->cg_cgx] = i β ffs_clusteracct:1963; blkno = cg_cgx * fs_fpg + bno β :1218 |
OOB write (int32 inc/dec/store) at fs_csp + 16Β·cg_cgx + 4 / fs_maxcluster + 4Β·cg_cgx β signed 32-bit index β Β±8/Β±32 GiB around the heap objects |
cg_freeoff |
cg_blksfree(cgp) base for ffs_clrblock/setbit/ffs_isblock/scanc β ffs_alloccgblk:1208-1209, ffs_alloccg:1081-1082, ffs_mapsearch:1837-1847, ffs_blkfree_cg:1532-1609 |
OOB read+write of single bits at cgbuf + cg_freeoff + bit/8 (32-bit offset β Β±2 GiB) |
cg_iusedoff |
cg_inosused(cgp) base for the inode-bitmap scan and setbit β ffs_nodealloccg:1383-1463, ffs_freefile:1791-1799 |
OOB read+write (movzbl scan, then setbit) |
cg_boff / cg_btotoff |
cg_blks(fs,cgp,cylno)[...]--, cg_blktot(cgp)[cylno]-- β ffs_alloccgblk:1215-1216, ffs_blkfree_cg:1550-1551 |
OOB int16/int32 write |
cg_clustersumoff / cg_clusteroff |
cg_clustersum(cgp)[len] rw-loop, sump[i] += cnt β ffs_clusteralloc:1257-1275, ffs_clusteracct:1893-1955 |
OOB int32 read/write |
cg_rotor / cg_frotor / cg_irotor |
scan start offsets β ffs_alloccgblk:1129, ffs_mapsearch:1836, ffs_nodealloccg:1410 |
OOB read (scanc length underflow) |
cg_nclusterblks |
loop bound reading *mapp++ β ffs_clusteralloc:1294-1308, ffs_clusteracct:1907 |
OOB read |
inode i_db[] β ffs_blkpref β cg = dtog(bpref) |
fs->fs_cs(fs, cg) guard before bread β ffs_alloccg:1010, ffs_nodealloccg:1370 |
OOB read at fs_csp + 16Β·cg |
The mount path never validates a single one of these fields
(ffs_mountfs checks only fs_magic/fs_bsize, ffs_vfsops.c:642-646),
and nothing re-checks them when the cg block is read at allocation time.
Nothing checks them at free time either (ffs_blkfree_cg, ffs_freefile).
Additionally, inconsistent-but-in-range cg metadata (per-cg cg_cs vs
fs_cstotal, bitmap vs counters) converts the kernel's own consistency
panic()s into fail-stop DoS from a crafted image: ffs_valloc:630
(dup alloc), ffs_nodealloccg:1451 (block not in map),
ffs_blkfree_cg:1542/1581 (freeing free block/frag),
ffs_clusteralloc:1317 (map mismatch).
Threat model
Crafted FFS media mounted by root (same model as DF-0820 / DF-3015).
The unprivileged trigger afterwards is a single creat/write in the
mounted filesystem β the very first allocation touches the poisoned cg.
On systems with vfs.usermount=1 (or in any scenario where an
unprivileged user can get a crafted image mounted β e.g. removable media
auto-mounting), this becomes unprivileged-user β arbitrary-offset kernel
memory corruption.
Primitive (verified on the guest, stock INVARIANTS kernel)
cg_cgx = 0x40000000β deterministicFatal trap 12, supervisor write, page not present, inffs_clusteracct:Stopped at ffs_clusteracct.isra.0+0x1eb: movl %eax,(%rdx,%rcx,4)β the storefs->fs_maxcluster[cg_cgx] = iatbase + 4Β·cg_cgx(panic1/2/3.txt). The same value three times β three fault addressesbase + 0x1_0000_0000, with boot-varying heap bases.cg_iusedoff = 0x20000000β deterministicFatal trap 12, supervisor read, inffs_nodealloccg:Stopped at ffs_nodealloccg+0x13f: movzbl (%rdi,%rax,1),%ecxβ theinosused[ipref]bitmap read atcgbuf + 0x20000000(panic4.txt).- Control run (identical image, no field patched) β allocation
succeeds, no panic (
run.setup.log,run.log).
A cg_cgx that lands on mapped memory instead of the guard page yields a silent single-int32 inc/dec at an attacker-chosen Β±offset β a corruption primitive, not a crash.
Reproduce (baseline, stock kernel)
# on the host, from the repo root: tar czf /tmp/p.tgz -C findings/poc/DF-3035 cgxtool.c setup3035.sh fs.h dinode.h ssh -F dfbsd-qemu/config dfbsd '/bin/sh -c "mkdir -p /root/poc && cat > /tmp/p.tgz && tar xzf /tmp/p.tgz -C /root/poc && cc -O -o /tmp/cgxtool /root/poc/cgxtool.c"' # in the guest (root): sh /root/poc/setup3035.sh cgx 0x40000000 # panics in ffs_clusteracct (write) sh /root/poc/setup3035.sh iusedoff 0x20000000 # panics in ffs_nodealloccg (read) sh /root/poc/setup3035.sh cgx none # control: no panic (see script) # panic evidence: dfbsd-qemu/vm.sh log (serial console)
Expected baseline: Fatal trap 12: page fault while in kernel mode,
fault code supervisor write data, page not present (cgx) or
supervisor read data, page not present (iusedoff), guest drops to db>.
Expected with fix.diff (validated, run.patched.log): no panic;
dd: /mnt/t0: No space left on device β the poisoned cg is rejected
(ffs_chkcg) and the allocator fails gracefully with ENOSPC; a clean
filesystem still allocates normally.
DF-3035 β VERDICT
Status: reproduced (impact: kernel memory corruption, attacker-offset OOB read + write; panic used as the observable). Fix validated: fixed.
What was tested
sys/vfs/ufs/ffs_alloc.c β every allocation/free path in the FFS
allocator reads the on-disk cylinder-group header and uses its fields
(cg_cgx, cg_freeoff, cg_iusedoff, cg_boff, cg_btotoff,
cg_clustersumoff, cg_clusteroff, cg_rotor, cg_frotor,
cg_irotor, cg_nclusterblks) as raw kernel-memory offsets/indexes
after nothing more than cg_chkmagic() (fs.h:398 β a magic
comparison). Mount-time validation does not exist for these fields
(ffs_vfsops.c:642-646 checks only fs_magic and fs_bsize bounds).
Baseline runs (stock INVARIANTS kernel, guest
DragonFly dfbsd 6.5-DEVELOPMENT ... #1: Mon Jun 29 14:18:01 UTC 2026)
All runs use a 128 MB image built by the guest's own newfs
(UFS1, 1 cylinder group, bsize 16384 / fsize 2048 / frag 8,
contigsumsize 7), with one 32-bit field of cg0's on-disk header
patched by cgxtool (offsets computed from the image's own
superblock). The mount itself never reads cg headers, so the crafted
image mounts read-write without complaint; the first allocation on it
executes the poisoned path.
| run | patched field | value | result |
|---|---|---|---|
| 0 (control) | β | β | first creat+16 KiB write succeeds, clean unmount (run.log) |
| 1 | cg_cgx |
0x40000000 | Fatal trap 12, supervisor write, page not present, ffs_clusteracct.isra.0+0x1eb: movl %eax,(%rdx,%rcx,4) @ 0xfffff8021776a200 (panic1.txt) |
| 2 | cg_cgx |
0x40040000 | same trap + same stopped instruction @ 0xfffff8018dce3600 (panic2.txt) |
| 3 | cg_cgx |
0x40000000 | same trap + same stopped instruction @ 0xfffff80218519500 (panic3.txt) |
| 4 | cg_iusedoff |
0x20000000 | Fatal trap 12, supervisor read, page not present, ffs_nodealloccg+0x13f: movzbl (%rdi,%rax,1),%ecx @ 0xfffff8007c136000 (panic4.txt) |
Why this is a write/read primitive, not "just a panic"
- The stopped instruction in runs 1β3 is the single indexed store
fs->fs_maxcluster[cgp->cg_cgx] = i(ffs_alloc.c:1963):movl %eax,(%rdx,%rcx,4)β address = base + 4 Γ (int32 index). The index is the on-diskcg_cgx(here 0x40000000 β +4 GiB). The fault is only observed because the chosen offset lands on an unmapped page; anycg_cgxwhose target is mapped yields a silent attacker-offset int32 store/inc/dec (fs_cs(cg_cgx).cs_nbfree--atffs_alloc.c:1213is the same class, Β±8 GiB reach). With the heap base ~0xfffff801xxxxxxxx, the reachable window covers the whole kernel heap and then some β signature: the three write faults sit atbootbase + 0x100000000with boot-varying bases (0xfffff8011776a200,0xfffff8008dbe3600,0xfffff80118519500), matchingfs_maxcluster + 4Β·cg_cgxin every run. - Run 4's stopped instruction is
inosused[ipref](ffs_alloc.c:1415/1393) β a byte read atcgbuf + cg_iusedoff, here +512 MiB. The same pointer is later written throughsetbit(inosused, ipref)(ffs_alloc.c:1463) when a zero bit is found: read primitive first, write primitive on the same field. cg_freeoff/cg_boff/cg_btotoff/cg_clustersumoff/cg_clusteroffare the identical pattern for the block bitmap and cylinder/cluster arrays (bit-level writes at Β±2 GiB, int16/int32 incs/decs) β traced in the finding table, not separately run: one field per boot is the observability limit (the first wild access traps), and the mechanism is line-for-line identical.
Exploitability assessment
- Trigger is a crafted filesystem image + one
creat/writeβ the mount itself needs root (orvfs.usermount=1setups / auto-mounting removable media, where the trigger becomes unprivileged). - The primitive is a relative kernel-memory write with a Β±8β32 GiB
32-bit-controlled displacement (csum dec/inc at 16-byte stride,
fs_maxclusterstore at 4-byte stride) plus bit-level writes through the bitmap offsets. No KASLR/SMAP/SMEP on this guest; heap base is boot-stable within a session, so a repeatable offset to a target object is realistic (e.g. pointcg_cgxso thatfs_csp[16Β·cg_cgx]lands on a neighbouring mount'sfs_csp, function-pointer-bearing structures, or refcounts). A full uid0 chain was not developed because the mount already requires root on the default configuration β the ceiling is arbitrary kernel memory corruption from a malicious disk image (or unprivileged corruption wherever users can get their image mounted). - The fail-stop
panic()s reachable with in-range inconsistent cg metadata (ffs_valloc:630dup alloc,ffs_nodealloccg:1451block not in map,ffs_blkfree_cg:1542/1581freeing free block/frag,ffs_clusteralloc:1317map mismatch) make the same image a reliable local DoS even without an out-of-range field.
Fix validation
fix.diff adds ffs_chkcg() β validating cg_cgx against the cg's
real index, rotors against their map sizes, and every map offset/size
against fs_cgsize (with int64 math, ordered like the on-disk layout) β
called after cg_chkmagic() in ffs_fragextend, ffs_alloccg,
ffs_clusteralloc, ffs_nodealloccg, ffs_blkfree_cg, and
ffs_freefile; plus a clamp of the preference-derived cg in
ffs_hashalloc() before it indexes fs_csp[].
Applied to the guest's /usr/src, make nativekernel KERNCONF=X86_64_GENERIC
(ffs_alloc.c compiled -Werror-clean), installed, rebooted
(run.patched.log for the full sequence):
- identical
cgx 0x40000000image β no panic;ddfailsNo space left on device(poisoned cg rejected β allocator returns 0 β ENOSPC); - identical
iusedoff 0x20000000image β no panic; same graceful ENOSPC; - control (unpatched image) β first allocation still succeeds
(
legit filesystem unaffected), clean unmount.
Baseline bad behaviour GONE; legitimate allocation behaviour preserved.
Non-goals / notes
- DF-0793 (async-TRIM lifetime) and DF-0794 (
fs_ncg==0) were given and are not re-verified here. - Superblock-geometry div-by-zeros reachable from this file
(
fs_maxbpg==0atffs_blkpref:805,fs_spc/fs_nsect/fs_npsectincbtocylno/cbtorpos,fs_frag>8indexingfragtbl/around/insideinffs_mapsearch) are the DF-0820/DF-0794 family (mount-time superblock validation) and are not re-filed.
Fix verification
fixedfix.diff applied to guest /usr/src (9 hunks clean), make nativekernel KERNCONF=X86_64_GENERIC -Werror-clean (ffs_alloc.o), installkernel, rebooted into #1 Sat Sep 5 14:02:46. Identical crafted images: cgx=0x40000000 -> NO panic, dd fails 'No space left on device' (poisoned cg rejected by ffs_chkcg -> ENOSPC); iusedoff=0x20000000 -> same graceful ENOSPC. Control image (cgx rewritten to its legitimate value 0): first allocation still succeeds (16384-byte file created) and unmounts cleanly, proving the validator does not reject legitimate newfs geometry. Baseline bad behaviour GONE.
findings/poc/DF-3035/run.patched.log
Confirmed kernel references
- sys/vfs/ufs/ffs_alloc.c:1010
- sys/vfs/ufs/ffs_alloc.c:1127
- sys/vfs/ufs/ffs_alloc.c:1213
- sys/vfs/ufs/ffs_alloc.c:1215
- sys/vfs/ufs/ffs_alloc.c:1218
- sys/vfs/ufs/ffs_alloc.c:1257
- sys/vfs/ufs/ffs_alloc.c:1294
- sys/vfs/ufs/ffs_alloc.c:1370
- sys/vfs/ufs/ffs_alloc.c:1383
- sys/vfs/ufs/ffs_alloc.c:1415
- sys/vfs/ufs/ffs_alloc.c:1463
- sys/vfs/ufs/ffs_alloc.c:1532
- sys/vfs/ufs/ffs_alloc.c:1836
- sys/vfs/ufs/ffs_alloc.c:1893
- sys/vfs/ufs/ffs_alloc.c:1963
- sys/vfs/ufs/fs.h:394
- sys/vfs/ufs/fs.h:398
- sys/vfs/ufs/ffs_vfsops.c:642
Detail
Exploit chain
crafted UFS1 image (cg_chkmagic-valid cg0, one poisoned field) mounted by root -> first creat/write on the mount -> ffs_balloc -> ffs_blkpref -> ffs_alloc -> ffs_hashalloc -> ffs_alloccg -> ffs_alloccgblk/ffs_nodealloccg -> wild write fs_maxcluster[cg_cgx]/fs_csp[cg_cgx] (attacker 32-bit index, store or inc/dec) or wild bitmap RMW at cgbuf+cg_freeoff/cg_iusedoff (attacker bit offset) -> with a heap-layout-stable target (no KASLR on this guest) point cg_cgx at a neighbouring kernel object: single-int32 decrement/Bit-flip corruption at an attacker-chosen relative address; panic when the offset is unmapped (the demonstrated observable). Full uid0 chain not developed: the mount precondition already requires root on the default configuration, so escalation adds nothing; the ceiling is arbitrary-offset kernel memory corruption (and unprivileged corruption wherever users can get images mounted).
Evidence (decisive lines)
['findings/poc/DF-3035/panic1.txt β Fatal trap 12, supervisor write, Stopped at ffs_clusteracct.isra.0+0x1eb: movl %eax,(%rdx,%rcx,4), fault 0xfffff8021776a200 (cg_cgx=0x40000000)', 'findings/poc/DF-3035/panic2.txt β same sink, cg_cgx=0x40040000, fault 0xfffff8018dce3600 (linear cg_cgx addressing)', 'findings/poc/DF-3035/panic3.txt β same sink, cg_cgx=0x40000000, fault 0xfffff80218519500 (boot-varying heap base + fixed 4*index displacement)', 'findings/poc/DF-3035/panic4.txt β Fatal trap 12, supervisor READ, Stopped at ffs_nodealloccg+0x13f: movzbl (%rdi,%rax,1), fault 0xfffff8007c136000 (cg_iusedoff=0x20000000)', 'findings/poc/DF-3035/run.setup.log β image build, cgxtool superblock/cg dump, patch confirmation, mount succeeds (mount never validates cg headers)', 'findings/poc/DF-3035/run.patched.log β fix.diff kernel: both poisoned images fail gracefully with ENOSPC, no panic; unpatched control image still allocates (16384-byte file), clean unmount', 'findings/poc/DF-3035/cgxtool.c + setup3035.sh β minimal crafted-image generator/patcher + trigger', 'findings/poc/DF-3035/fix.diff β ffs_chkcg() validator called from all six cg consumers + ffs_hashalloc cg clamp; applied to guest /usr/src, nativekernel -Werror-clean, installed, rebooted']
PoC changes
No prior PoC seed β authored fresh. cgxtool.c computes all offsets from the image's own superblock via the tree's fs.h (needed the ufs_types.h 32-bit ufs_daddr_t/ufs_time_t typedefs; an int64 first attempt misaligned the superblock). setup3035.sh gained a notrigger mode so setup output could be captured before the panic kills sshd. Two early validator bugs in fix.diff were caught against the real newfs layout before building (btotoff=168 == offsetof(struct cg,cg_space), and the fpg-sized bitmap scan region legitimately overlapping clustersumoff by 4 bytes) β the fix must reject poison without rejecting legitimate filesystems, and the control run proves it does not.
Verified recommended fix
Add ffs_chkcg() validating every cg-header field (cg_cgx, rotors, and all map offsets/sizes against fs_cgsize) after each cg bread() in ffs_alloc.c, and clamp the bpref-derived cg in ffs_hashalloc() before it indexes fs_csp[] (fix.diff, fix-validated in-guest).
Verdict
Attacker-offset out-of-bounds kernel READ and WRITE reproduced deterministically on the stock INVARIANTS guest kernel from a crafted UFS1 image whose cylinder-group header carries a magic value plus one poisoned field. ffs_mountfs validates only fs_magic/fs_bsize (ffs_vfsops.c:642-646) and the allocator applies only cg_chkmagic() (fs.h:398, a magic compare) before using on-disk cg fields as kernel-memory offsets and indexes: cg_cgx -> fs_csp[16cg_cgx].cs_nbfree-- and fs_maxcluster[4cg_cgx] stores (ffs_alloc.c:1213,1963); cg_freeoff/cg_iusedoff/cg_boff/cg_btotoff/cg_clustersumoff/cg_clusteroff -> bit/int16/int32 read-modify-write through cgbuf+offset (ffs_alloc.c:1208-1216,1383-1463,1532-1609,1893-1955); cg_rotor/cg_frotor/cg_irotor/cg_nclusterblks -> OOB scan bounds (1129,1294,1410,1836); plus inode-derived bpref -> dtog() -> fs_csp[] OOB read before bread (1010,1370). Proven by: cg_cgx=0x40000000 -> Fatal trap 12 supervisor WRITE page-not-present at ffs_clusteracct.isra.0+0x1eb movl %eax,(%rdx,%rcx,4) with fault address = fs_maxcluster + 4*0x40000000 in three independent boots (panic1/2/3.txt); cg_iusedoff=0x20000000 -> Fatal trap 12 supervisor READ at ffs_nodealloccg+0x13f movzbl (%rdi,%rax,1), the inosused[] bitmap read at cgbuf+512MiB (panic4.txt); identical unpatched image allocates cleanly (control run). Panic is only the observable: any offset landing on mapped memory yields a silent attacker-relative int32 inc/dec/store (csum counters) or bit write (block/inode bitmaps), reach +/-8..32GiB around kernel heap objects via the signed 32-bit fields. Fail-stop panics from merely inconsistent in-range cg metadata (dup alloc 630, block-not-in-map 1451, freeing-free 1542/1581, map-mismatch 1317) make the same image a reliable DoS. Trigger model = crafted media mounted by root (DF-0820/DF-3015 class) with a single creat/write as the poisoned allocation; with vfs.usermount=1 or auto-mounted removable media the corruption itself is unprivileged. Root cause is distinct from DF-0820 (superblock geometry at mount) and DF-0794 (fs_ncg==0): this is the per-cylinder-group header consumed lazily at alloc/free time with no validation anywhere.
No comments yet.