DF-2756
vn_read has no VDIR gate: read() on a directory fd is dispatched to VOP_READ, and ffs_read explicitly accepts VDIR, exposing raw directory blocks (deleted-entry residue) instead of returning EISDIR
| Field | Value |
|---|---|
| ID | DF-2756 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N |
| CWE | CWE-668 Exposure of Resource to Wrong Sphere |
| File | sys/kern/vfs_vnops.c |
| Lines | 749-754 (ffs acceptance ufs_readwrite.c:81-85) |
| Area | kern |
| Confidence | certain |
| Discovered | 2026-08-30 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | kernleak |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
vn_read performs no v_type check, and ffs_read treats VDIR as legal
(else if (vp->v_type != VREG && vp->v_type != VDIR) panic), so on
UFS-family mounts read() on a directory fd returns raw on-disk
directory blocks — violating POSIX's mandatory EISDIR and disclosing
inter-entry slack space (d_reclen padding) containing residue of
removed entries (names, inode numbers) from before the reader existed.
On-disk data residue, not kernel memory. hammer2 and tmpfs reject dir
reads (verified), so impact requires a UFS/ext2 mount.
Recommended fix
Add if (vp->v_type == VDIR) return (EISDIR); at the common layer in
vn_read() before taking the vnode lock (mirrors FreeBSD), and/or make
ffs_read return EISDIR for VDIR.
Timeline
- 2026-08-30 Discovered during pass-2 audit of vfs_vnops.c (GLM 5.3).
No comments yet.