β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-3026

tmpfs_write never re-checks APPEND/IMMUTABLE per write β€” flags set after open are defeated by pre-existing writable fds (UFS enforces APPEND per-write)

Field Value
ID DF-3026
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
CWE CWE-285
File sys/vfs/tmpfs/tmpfs_vnops.c
Lines 268-270, 666-943 (contrast ufs_readwrite.c:239)
Area vfs/tmpfs
Confidence likely
Discovered 2026-09-02
Pass 2 (GLM 5.3 second pass)
Bucket base:vfs
Reported pending
Known CVE none
CVE match novel

Summary

tmpfs enforces the APPEND flag only at open time and never in tmpfs_write β€” no tn_flags check anywhere in the write path. vn_writechk only covers VTEXT/EROFS, so nothing else re-checks. UFS re-validates at every write ('if ((ip->i_flags & APPEND) && uio->uio_offset != ip->i_size) return EPERM'). Consequence: a writable fd opened before root sets SF_APPEND/SF_IMMUTABLE (incident-response freezing of a /tmp artifact) keeps writing β€” pwrite() at an explicit offset overwrites the middle of an append-only tmpfs file, and writes to an immutable-flagged file succeed. Setting these flags requires root, so the bypass matters only against administrator intent (hammer2 shares the gap; UFS is the reference behavior). Untested (needs root to set flags). Fix: add the UFS-exact check to tmpfs_write near the VREG check.

Timeline

  • 2026-09-02 Discovered during pass-2 audit of tmpfs_vnops.c (GLM 5.3). DF-0779 re-verified, not re-reported; positive-offset 2^63 wrap refuted live (unsigned size_t promotion β€” both probe pwrites returned EFBIG).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3026 Β· 8 files
FileTypeDescriptionSize
README.md β€” 308 B ↓ raw
VERDICT.md β€” 1.5 KB ↓ raw
df3026.c β€” 1.8 KB view raw
env.txt β€” 248 B view raw
fix.diff β€” 621 B view raw
manifest.json β€” 611 B view raw
run.log β€” 346 B view raw
verdict.json β€” 1.7 KB view raw

DF-3026 - tmpfs_write never re-checks APPEND/IMMUTABLE per write (UFS does)

Severity Low | verdict: reproduced | impact: none

Reproduce

Sources in this directory; build with cc -O2 -o <bin> <src> -pthread on the guest.

See VERDICT.md for the full narrative and run.log for the decisive output.

VERDICT.md
↓ download raw

DF-3026 verification

Kernel: DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64

Behaviorally reproduced with a differential control. As unprivileged user maxx: opened a tmpfs file O_WRONLY (plain), then root set SF_APPEND (chflags sappnd): a pwrite() at offset 0 (middle-of-file) SUCCEEDS on tmpfs (ret=1) while the identical sequence on a UFS filesystem returns EPERM (ufs_readwrite.c:239 per-write APPEND check). Phase 2: root set SF_IMMUTABLE (schg) - a write() through the pre-opened fd succeeds on tmpfs (and, notably, on UFS too: IMMUTABLE is open-time-only there, so only the APPEND half is a tmpfs-specific divergence). Administrator-intent bypass confirmed exactly as filed; no memory-safety impact.

Kernel references

Fix

See fix.diff.

Fix validation (A/B on rebuilt kernel #0 Sun Oct 25 06:10:12 UTC 2026)

fix_status: fixed - A/B validated on the fix kernel: PHASE1 pwrite(mid) ret=-1 EPERM and PHASE2 write ret=-1 EPERM under sappnd/schg (baseline: both succeeded)

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_testable
↓ fix.diffper-fix-DF-3026

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md + run.log + sources

PoC changes

adjusted from finding sketch to guest syscall/layout reality

Verified recommended fix

fix.diff adds the UFS-exact per-write APPEND/IMMUTABLE checks to tmpfs_write near the VREG check; A/B validated on the fixed kernel (see VERDICT.md).

Verdict

Behaviorally reproduced with a differential control. As unprivileged user maxx: opened a tmpfs file O_WRONLY (plain), then root set SF_APPEND (chflags sappnd): a pwrite() at offset 0 (middle-of-file) SUCCEEDS on tmpfs (ret=1) while the identical sequence on a UFS filesystem returns EPERM (ufs_readwrite.c:239 per-write APPEND check). Phase 2: root set SF_IMMUTABLE (schg) - a write() through the pre-opened fd succeeds on tmpfs (and, notably, on UFS too: IMMUTABLE is open-time-only there, so only the APPEND half is a tmpfs-specific divergence). Administrator-intent bypass confirmed exactly as filed; no memory-safety impact.