Author: glebius
Date: Wed Jul  9 07:48:05 2014
New Revision: 268450
URL: http://svnweb.freebsd.org/changeset/base/268450

Log:
  In several cases in ip_output() we obtain reference on ifa. Do not
  leak it.
  
  Together with:        asomers, np
  Sponsored by: Nginx, Inc.

Modified:
  head/sys/netinet/ip_output.c

Modified: head/sys/netinet/ip_output.c
==============================================================================
--- head/sys/netinet/ip_output.c        Wed Jul  9 05:51:59 2014        
(r268449)
+++ head/sys/netinet/ip_output.c        Wed Jul  9 07:48:05 2014        
(r268450)
@@ -136,6 +136,7 @@ ip_output(struct mbuf *m, struct mbuf *o
        struct rtentry *rte;    /* cache for ro->ro_rt */
        struct in_addr odst;
        struct m_tag *fwd_tag = NULL;
+       int have_ia_ref;
 #ifdef IPSEC
        int no_route_but_check_spd = 0;
 #endif
@@ -202,6 +203,7 @@ ip_output(struct mbuf *m, struct mbuf *o
        gw = dst = (struct sockaddr_in *)&ro->ro_dst;
 again:
        ia = NULL;
+       have_ia_ref = 0;
        /*
         * If there is a cached route, check that it is to the same
         * destination and is still up.  If not, free it and try again.
@@ -238,6 +240,7 @@ again:
                        error = ENETUNREACH;
                        goto bad;
                }
+               have_ia_ref = 1;
                ip->ip_dst.s_addr = INADDR_BROADCAST;
                dst->sin_addr = ip->ip_dst;
                ifp = ia->ia_ifp;
@@ -250,6 +253,7 @@ again:
                        error = ENETUNREACH;
                        goto bad;
                }
+               have_ia_ref = 1;
                ifp = ia->ia_ifp;
                ip->ip_ttl = 1;
                isbroadcast = in_broadcast(dst->sin_addr, ifp);
@@ -261,6 +265,8 @@ again:
                 */
                ifp = imo->imo_multicast_ifp;
                IFP_TO_IA(ifp, ia);
+               if (ia)
+                       have_ia_ref = 1;
                isbroadcast = 0;        /* fool gcc */
        } else {
                /*
@@ -552,8 +558,11 @@ sendit:
 #endif
                        error = netisr_queue(NETISR_IP, m);
                        goto done;
-               } else
+               } else {
+                       if (have_ia_ref)
+                               ifa_free(&ia->ia_ifa);
                        goto again;     /* Redo the routing table lookup. */
+               }
        }
 
        /* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */
@@ -582,6 +591,8 @@ sendit:
                m->m_flags |= M_SKIP_FIREWALL;
                m->m_flags &= ~M_IP_NEXTHOP;
                m_tag_delete(m, fwd_tag);
+               if (have_ia_ref)
+                       ifa_free(&ia->ia_ifa);
                goto again;
        }
 
@@ -694,6 +705,8 @@ passout:
 done:
        if (ro == &iproute)
                RO_RTFREE(ro);
+       if (have_ia_ref)
+               ifa_free(&ia->ia_ifa);
        return (error);
 bad:
        m_freem(m);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to