re pf bug on bugs@:
apparently the crash is caused by the stack corruption that happens
in pf_map_addr as it expects to get an array of struct pf_src_node
pointers, not just one pointer. the bug was introduced about four
years ago, but somehow (stack layout?) went unnoticed.
the proper fix is to pass an empty array of size PF_SN_MAX as done
in other places.
i've verified that this fixes the issue for me and arjan is going
to verify as well.
while here, i think it makes sense to initialize src_nodes list
head and while it's essentially a noop, if we convert it to
something else where it matters, proper initialization might get
lost.
diff --git sys/net/pf.c sys/net/pf.c
index 5177466..38e3423 100644
--- sys/net/pf.c
+++ sys/net/pf.c
@@ -3204,15 +3204,16 @@ void
pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
{
struct pf_rule *r = s->rule.ptr;
- struct pf_src_node *sn = NULL;
+ struct pf_src_node *sns[PF_SN_MAX];
s->rt_kif = NULL;
if (!r->rt)
return;
+ bzero(sns, sizeof(sns));
switch (s->key[PF_SK_WIRE]->af) {
#ifdef INET
case AF_INET:
- pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL, &sn,
+ pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL, sns,
&r->route, PF_SN_ROUTE);
s->rt_kif = r->route.kif;
s->natrule.ptr = r;
@@ -3220,7 +3221,7 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
#endif /* INET */
#ifdef INET6
case AF_INET6:
- pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL, &sn,
+ pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL, sns,
&r->route, PF_SN_ROUTE);
s->rt_kif = r->route.kif;
s->natrule.ptr = r;
@@ -3710,6 +3711,8 @@ pf_create_state(struct pf_pdesc *pd, struct pf_rule *r,
struct pf_rule *a,
#endif
s->set_prio[0] = act->set_prio[0];
s->set_prio[1] = act->set_prio[1];
+ SLIST_INIT(&s->src_nodes);
+
switch (pd->proto) {
case IPPROTO_TCP:
s->src.seqlo = ntohl(th->th_seq);