On Mon, Jan 25, 2021 at 06:17:02PM +0100, Alexandr Nedvedicky wrote:
> Hello,
>
> pf_route() might leak a refence to ifp.
oh no :(
> > Index: sys/net/pf.c
> > ===================================================================
> > RCS file: /cvs/src/sys/net/pf.c,v
> > retrieving revision 1.1101
> > diff -u -p -r1.1101 pf.c
> > --- sys/net/pf.c 19 Jan 2021 22:22:23 -0000 1.1101
> > +++ sys/net/pf.c 22 Jan 2021 07:33:31 -0000
>
> </snip>
>
> > @@ -5998,48 +5994,40 @@ pf_route(struct pf_pdesc *pd, struct pf_
> >
> > ip = mtod(m0, struct ip *);
> >
> </snip>
> > +
> > + ifp = if_get(rt->rt_ifidx);
> > if (ifp == NULL)
> > goto bad;
>
> here we get a reference to ifp.
yep.
> > @@ -6082,9 +6060,9 @@ pf_route(struct pf_pdesc *pd, struct pf_
> > */
> > if (ip->ip_off & htons(IP_DF)) {
> > ipstat_inc(ips_cantfrag);
> > - if (r->rt != PF_DUPTO)
> > + if (s->rt != PF_DUPTO)
> > pf_send_icmp(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG,
> > - ifp->if_mtu, pd->af, r, pd->rdomain);
> > + ifp->if_mtu, pd->af, s->rule.ptr, pd->rdomain);
> > goto bad;
>
> here we do 'goto bad', which does not call if_put().
yes it does. the whole chunk with the diff applied is:
done:
if (s->rt != PF_DUPTO)
pd->m = NULL;
if_put(ifp);
rtfree(rt);
return;
bad:
m_freem(m0);
goto done;
}
bad drops the mbuf and then goes to done.