DF-0472 / panic.txt
DF-0472 - OOB function-pointer call -> kernel panic (trap 9, GP fault)
=====================================================================
(excerpt from dfbsd-qemu/boot.log; guest entered DDB, ssh died)
Trigger: ./panic (root)
- setsockopt(IP_FW_X, IP_FW_ADD) installs a rule with cmd[0].module=0x80,
cmd[0].opcode=0x80, cmd_len=255 (the unvalidated field).
- sysctl net.inet.ip.fw3.enable=1 re-hooks pfil.
- one outbound UDP packet -> ip_fw3_check_out -> ip_fw3_chk iterates the
rule chain, hits our rule first, and at sys/net/ipfw3/ip_fw3.c:506 does
(filter_funcs[cmd->module][cmd->opcode])(...);
filter_funcs is [10][100]; index 0x80*100+0x80 = 12928 is ~11928 entries
PAST the 1000-entry array => reads a wild pointer from neighbouring kernel
memory and CALLS it.
ipfw3.ko was loaded at 0xffffffff82600000 (kldstat); the faulting RIP
0xffffffff826001a4 == ipfw3.ko+0x1a4, ddb symbolises it as ip_fw3_chk+0x1a4.
The fault is a #GP (trap 9) on a `ret` -- the wild call ran a few garbage
instructions off the corrupted pointer/stack and faulted returning. This
proves the attacker-controlled module/opcode reached the indirect call.
------------------------------------------------------------------------
Fatal trap 9: general protection fault while in kernel mode
cpuid = 5; lapic id = 5
instruction pointer = 0x8:0xffffffff826001a4
stack pointer = 0x10:0xfffff8008d271760
frame pointer = 0x10:0xfffff8008d2717d0
code segment = base 0x0, limit 0xfffff, type 0x1b
= DPL 0, pres 1, long 0, def32 0, gran 1
processor eflags = interrupt enabled, resume, IOPL = 0
current process = Idle
current thread = pri 12
kernel: type 9 trap, code=0
CPU5 stopping CPUs: 0x0000001f
stopped
Stopped at ip_fw3_chk+0x1a4: ret
db>
------------------------------------------------------------------------
IMPACT: a kernel memory-corruption primitive (attacker-influenced indirect
call). On this guest SMEP/SMAP are OFF, so the called pointer could be steered
at userspace shellcode (commit_creds(prepare_kernel_cred(0))) given a heap-
grooming chain that lands a chosen value at filter_funcs[0x80][0x80]; here it
is demonstrated at the panic (DoS) level. Root-only trigger (raw socket +
firewall enable).