Missing sopt_valsize validation causes OOB heap read in every set-mutation handler
Summary
move_set move_rule swap toggle flush all cast sopt->sopt_val to (int*) deref without checking sopt_valsize large enough. With small valsize(e.g. setsockopt buf 1) deref reads past kmalloc sopt_val buffer into adjacent slab bytes. Needs 8 bytes(move/swap) 4 bytes(toggle/flush) checks none. ipfw2 sibling validates everywhere ipfw3 does not. OOB values consumed only inside range checks (0,32) never returned no direct disclosure. Defense-in-depth hardening. [VERIFIED pass2: reproduced behavioral oracle - 1-byte TOGGLE payload with stale residue toggles set 5 while clean residue is rejected, bytes past sopt_valsize decide kernel state; EINVAL-before-read fix A/B]
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2593 Β· 2 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fw3_set_oob.c | β | 3.4 KB | view raw | |
| run.log | β | 300 B | view raw |
Fix verification
not_testableConfirmed kernel references
Detail
Evidence (decisive lines)
fw3_set_oob.log: case A delta 0x20 vs case B delta 0 -> OOB READ CONFIRMED line
PoC changes
raw setsockopt oracle through the real module
Verified recommended fix
validate sopt_valsize >= sizeof(int) (or 2 ints) in every set handler (in the rebuilt ipfw3 module fix)
Verdict
All five set-mutation handlers (ip_fw3_set.c:105-252) cast sopt->sopt_val to int and deref 4-8 bytes with no sopt_valsize check (staged by kern_setsockopt as kmalloc(valsize), uipc_syscalls.c:1257). Behavioral oracle via IP_FW_SET_TOGGLE with a 1-byte payload: the ip_fw_x_header residue immediately past the 1 logical byte completes the int; residue 00 00 00 -> num=5 -> set 5 toggled (IP_FW_SET_GET delta 0x20), residue 01 01 00 -> *num=0x01010005 -> rejected (delta 0). Same user payload, divergent kernel state changes driven by bytes past sopt_valsize. Values only feed range checks (never returned) -- hardening-class as filed. Root-only op path (raw socket).
No comments yet.