copyin return value silently discarded before prop_dictionary_copyin
Summary
Line 345 error=copyin(vqa->pref,...) overwritten by line 346 error=prop_dictionary_copyin without testing copyin result. Invalid pref pointer -> uninitialized pref passed to prop_dict_copyin. Stale EFAULT not propagated. Gated by vfs_quota_enabled.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0144 Β· 13 files| File | Type | Description | Size | |
|---|---|---|---|---|
| df0144_poc.c | trigger-source | vquotactl(invalid pref=0x1) -> discarded copyin -> panic | 2.0 KB | view raw |
| build.sh | build-script | cc -o df0144_poc df0144_poc.c | 92 B | view raw |
| run.sh | run-script | ./df0144_poc | 248 B | view raw |
| build.log | build-log | final successful build | 13 B | view raw |
| run.log | run-log | baseline run: guest panicked (panic signature recorded) | 1.0 KB | view raw |
| panic.txt | panic-signature | kmem_slab_alloc exhausted via _prop_object_copyin <- sys_vquotactl | 1.1 KB | view raw |
| panic_raw.txt | panic-signature | raw boot.log panic excerpt | 271 B | view raw |
| env.txt | environment | uname + cc, vfs.quota_enabled=1 | 188 B | view raw |
| fix.diff | suggested-fix | check copyin error before prop_dictionary_copyin | 334 B | view raw |
| fix_run.log | fix-run-log | patched: vquotactl returns EFAULT errno=14, NO panic, guest up | 100 B | view raw |
| VERDICT.md | verdict | full narrative | 2.5 KB | β 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 |
DF-0144 β copyin return value silently discarded before prop_dictionary_copyin
Verdict: REPRODUCED (local kernel panic / DoS, unprivileged)
The discarded copyin() result is confirmed live as a deterministic kernel
panic triggered by an unprivileged user. The impact is stronger than the
"stale EFAULT" the finding describes: the uninitialized struct plistref is
fed to _prop_object_copyin, which interprets it as a serialized object and
drives kmalloc until kernel_map is exhausted β panic.
The bug (sys/kern/vfs_quota.c:345-346)
error = copyin(vqa->pref, &pref, sizeof(pref)); /* line 345 */
error = prop_dictionary_copyin(&pref, &dict); /* line 346 β overwrites rc */
copyin()'s return is overwritten on the very next line without being tested.
With an invalid pref pointer (vqa->pref = 0x1), copyin fails with EFAULT
and leaves pref uninitialized; prop_dictionary_copyin(&pref, &dict)
then runs on garbage. sys_vquotactl performs no privilege check, so any
user can reach this.
Evidence (live panic)
Trigger (as unprivileged maxx, vfs.quota_enabled=1):
syscall(SYS_vquotactl, "/tmp", (void*)0x1)
Serial console (dfbsd-qemu/boot.log):
panic: kmem_slab_alloc(): kernel_map ran out of space!
kmem_slab_alloc() at kmem_slab_alloc+0x42b
kmem_slab_alloc() at kmem_slab_alloc+0x42b
_kmalloc() at _kmalloc+0x5be
_prop_object_copyin.isra.0() at _prop_object_copyin.isra.0+0x35
sys_vquotactl() at sys_vquotactl+0x50
sys_xsyscall() at sys_xsyscall+0x89
Debugger("panic")
vm.sh status β down immediately after. The call chain
sys_vquotactl+0x50 β _prop_object_copyin β _kmalloc β kmem_slab_alloc(panic)
is exactly the discarded-copyin path (line 346 reached with bad pref).
Exploit chain
none (no memory-corruption primitive to escalate) β this is a DoS panic.
The "primitive" is an unbounded kernel allocation driven by attacker-influenced
garbage; it reliably exhausts kernel_map and panics before any useful
corruption object can be groomed. There is no write/UAF to convert to uid=0;
the realistic impact ceiling is reliable local DoS (unprivileged kernel
panic), which is the demonstrated outcome.
Fix
fix.diff adds the missing if (error) return (error); after the copyin.
git apply --check passes. On a fixed kernel the same syscall returns EFAULT
(errno 14) cleanly without calling prop_dictionary_copyin.
Fix validation
See Phase 8 β the single-fix kernel returns EFAULT (no panic) on the same trigger that panicked the unpatched baseline.
Fix verification
fixedvalidated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
REPRODUCED (live panic). copyin result discarded -> uninitialized pref -> kmem exhaustion panic. Unprivileged vquotactl.
No comments yet.