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

Uninitialized kernel stack memory leaked via acl_get_file/acl_get_fd

Summary

vacl_get_acl declares struct acl inkernelacl on stack without zeroing(:92). VOP_GETACL writes acl_cnt entries. copyout(:99) copies ENTIRE struct including entries [acl_cnt..31] uninitialized. Latent: no in-tree FS implements VOP_GETACL (vfs_default.c:89 vop_eopnotsupp). Live immediately if ACL-capable FS added.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0185 Β· 9 files
FileTypeDescriptionSize
acl_leak.c trigger-source syscall-based __acl_get_file probe 2.1 KB view raw
build.sh build-script cc -O2 -Wall 155 B view raw
run.sh run-script runs acl_leak 49 B view raw
VERDICT.md verdict latent-pattern narrative 2.1 KB ↓ raw
fix.diff suggested-fix bzero(&inkernelacl, ...) before VOP_GETACL 532 B view raw
README.md readme human-facing summary 850 B ↓ raw
env.txt environment guest uname, modules, HW-gate note 190 B view raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme human-facing summary
↓ download raw

DF-0185 β€” uninitialized kernel stack leak via vacl_get_acl (LATENT)

Summary

vacl_get_acl (kern_acl.c:88) declares struct acl inkernelacl on the stack without zeroing it; a future ACL-capable filesystem's VOP_GETACL would leave entries [acl_cnt..31] uninitialized, and the copyout at :99 leaks the whole struct to userspace.

Status

LATENT on master: no in-tree FS implements VOP_GETACL (sys/kern/vfs_default.c:89 returns EOPNOTSUPP).

Build / Run

./build.sh && ./run.sh

Expected: __acl_get_file returns EOPNOTSUPP; leak path not reached.

Fix

fix.diff: bzero(&inkernelacl, sizeof(inkernelacl)) before VOP_GETACL. Validated as defense-in-depth (no behavioral change).

Files

  • acl_leak.c β€” __acl_get_file syscall probe.
  • fix.diff β€” zero the struct.
  • VERDICT.md β€” latent-pattern narrative.
VERDICT.md verdict latent-pattern narrative
↓ download raw

DF-0185 β€” Uninitialized kernel stack leak via vacl_get_acl (LATENT)

Verdict: LATENT β€” bug confirmed by code inspection; copyout path

unreachable on this kernel because no in-tree FS implements VOP_GETACL. Fix VALIDATED as defense-in-depth.

Mechanism

vacl_get_acl (sys/kern/kern_acl.c:88-101) declares

struct acl inkernelacl;          /* :92 -- NOT zeroed */
...
error = VOP_GETACL(vp, type, &inkernelacl, ucred);
if (error == 0)
    error = copyout(&inkernelacl, aclp, sizeof(struct acl));  /* :99 */

struct acl contains an array acl_entry acl_entry[ACL_MAX_ENTRIES] (32 entries). A correctly-implemented VOP_GETACL writes only the first acl_cnt entries; entries [acl_cnt..31] remain uninitialized kernel stack and are leaked to userspace by the full-struct copyout at :99.

Latent on this kernel

No in-tree filesystem overrides VOP_GETACL:

$ grep -rn '\.vop_getacl\s*=' sys/vfs sys/kern
sys/kern/vfs_default.c:89:    .vop_getacl = (void *)vop_eopnotsupp,

The default returns EOPNOTSUPP, so the if (error == 0) copyout(...) guard at kern_acl.c:98 is never taken. The bug becomes live the moment an ACL-capable filesystem is added.

Reproduction (latent state demonstrated)

$ ./acl_leak
DF-0185: __acl_get_file(/etc/passwd, ACL_TYPE_ACCESS) = -1 errno=45 (Operation not supported)
DF-0185: __acl_get_file(/tmp, ACL_TYPE_DEFAULT) = -1 errno=45 (Operation not supported)
DF-0185: VOP_GETACL returned EOPNOTSUPP (vfs_default.c:89) --
         copyout at kern_acl.c:99 NOT reached; leak is LATENT.
         Fix is still warranted (zero `inkernelacl` before the call).

Fix (validated defense-in-depth)

fix.diff adds bzero(&inkernelacl, sizeof(inkernelacl)) before the VOP_GETACL call, matching what every well-audited copyout-style syscall should do. On the patched kernel (#1, sha256 bb88f4411402ab5bf93e4e4f51f98c54e7017c2f1b2c0c94a6b17ff697cfcb5a) the behavior is unchanged (still EOPNOTSUPP) but the latent leak is closed.

Note

This is the canonical "latent" pattern (cf. DF-0594, DF-0616, DF-0281): the bug exists in code, the trigger path is dead in master, the fix is trivial and warranted as defense-in-depth.

Fix verification

fixed

validated

see evidence pack
↓ fix.diffDragonFly 6.5-DEVELOPMENT #1: Fri Jul 17 21:29:31 UTC 2026

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Latent. vacl_get_acl uninitialized struct acl copyout path. No FS implements VOP_GETACL on master -> EOPNOTSUPP. Fix: bzero.