pfr_walktree()/PFRW_GET_ASTATS copies 4 uninitialized kernel-stack bytes per entry to userspace via DIOCRGETASTATS
Summary
The PFRW_GET_ASTATS branch builds 'struct pfr_astats as;' on the kernel stack, bzeros only the 20-byte embedded pfras_a, then COPYOUTs all 96 bytes - the 4 alignment-pad bytes between pfras_a and the 8-byte-aligned pfras_packets[] are never written and leak kernel stack residue. VERIFIED on guest: deterministically returned 01f8ffff (a truncated DFly kernel-VM stack pointer fragment) in 96/96 entries across 3 runs (with a stack-dirtying DIOCRTSTADDRS between iterations). Root-only (/dev/pf 0600) info leak - Low. Fix: bzero(&as, sizeof(as)) at the top of the branch.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3338 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| astats_padleak.c | trigger-source | DIOCRGETASTATS reader inspecting the pad bytes | 3.3 KB | view raw |
| run.log | run-log | 3 runs x 12 iterations, 96/96 non-zero | 21.9 KB | view raw |
| leak_sample.txt | leak-sample | 01f8ffff (kernel stack ptr fragment) | 415 B | view raw |
| verdict.json | verdict | machine verdict | 1.8 KB | view raw |
Fix verification
not_testableConfirmed kernel references
Detail
Exploit chain
root issues DIOCRGETASTATS on a populated table -> kernel copyout of 96-byte entries with bytes 20..23 uninitialized -> raw ioctl reader observes kernel stack residue.
Evidence (decisive lines)
["run.log: 'pad(20..23)=01f8ffff' in 96/96 entries over 3 runs", 'leak_sample.txt']
PoC changes
added #include
Verified recommended fix
bzero(&as, sizeof(as)) before filling in the PFRW_GET_ASTATS branch of pfr_walktree().
Verdict
REPRODUCED: pfr_walktree() PFRW_GET_ASTATS (pf_table.c:1058-1081) copies a stack struct pfr_astats to userspace without initializing the 4 alignment-pad bytes between the 20-byte pfras_a and the 8-byte-aligned pfras_packets[]; 01f8ffff observed in 96/96 entries across 3 runs on the stock kernel - kernel-stack residue (0xfffff801... is DFly kernel-VM). Root-only (pf 0600), 4 bytes/entry -> Low.
No comments yet.