Hello,

pf_route() might leak a refence to ifp.

> 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.

>  
> -     if (pd->kif->pfik_ifp != ifp) {
> +     /* A locally generated packet may have invalid source address. */
> +     if ((ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET &&
> +         (ifp->if_flags & IFF_LOOPBACK) == 0)
> +             ip->ip_src = ifatoia(rt->rt_ifa)->ia_addr.sin_addr;
> +
> +     if (pd->dir == PF_IN) {
>               if (pf_test(AF_INET, PF_OUT, ifp, &m0) != PF_PASS)
>                       goto bad;
>               else if (m0 == NULL)
> @@ -6052,16 +6040,6 @@ pf_route(struct pf_pdesc *pd, struct pf_
>               ip = mtod(m0, struct ip *);
>       }
>  
> -     rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid);
> -     if (!rtisvalid(rt)) {
> -             ipstat_inc(ips_noroute);
> -             goto bad;
> -     }
> -     /* A locally generated packet may have invalid source address. */
> -     if ((ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET &&
> -         (ifp->if_flags & IFF_LOOPBACK) == 0)
> -             ip->ip_src = ifatoia(rt->rt_ifa)->ia_addr.sin_addr;
> -
>       in_proto_cksum_out(m0, ifp);
>  
>       if (ntohs(ip->ip_len) <= ifp->if_mtu) {
> @@ -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().

>       }
>  
> @@ -6108,8 +6086,9 @@ pf_route(struct pf_pdesc *pd, struct pf_
>               ipstat_inc(ips_fragmented);
>  
>  done:
> -     if (r->rt != PF_DUPTO)
> +     if (s->rt != PF_DUPTO)
>               pd->m = NULL;
> +     if_put(ifp);
>       rtfree(rt);
>       return;
>  


pf_route6() suffers from the same issue.


thanks and
regards
sashan

Reply via email to