Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Dec 2019 01:12:54 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r356107 - head/sys/net
Message-ID:  <201912270112.xBR1CsAc053618@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Fri Dec 27 01:12:54 2019
New Revision: 356107
URL: https://svnweb.freebsd.org/changeset/base/356107

Log:
  Plug some ifaddr refcount leaks.
  
  - Only take an ifaddr ref in in rt_exportinfo() if the caller explicitly
    requests it.  Take care to release it in this case.
  - Don't unconditionally take a ref in rtrequest1_fib().  rt_getifa_fib()
    will acquire a reference, in which case we would previously acquire
    two references.
  - Stop taking a reference in rtinit1() before calling rtrequest1_fib().
    rtrequest1_fib() will acquire a reference for the RTM_ADD case.
  
  PR:		242746
  Reviewed by:	melifaro (previous version)
  Tested by:	ghuckriede@blackberry.com
  MFC after:	1 week
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D22912

Modified:
  head/sys/net/route.c

Modified: head/sys/net/route.c
==============================================================================
--- head/sys/net/route.c	Fri Dec 27 01:11:26 2019	(r356106)
+++ head/sys/net/route.c	Fri Dec 27 01:12:54 2019	(r356107)
@@ -833,7 +833,7 @@ rtrequest_fib(int req,
  * to reflect size of the provided buffer. if no NHR_COPY is specified,
  * point dst,netmask and gw @info fields to appropriate @rt values.
  *
- * if @flags contains NHR_REF, do refcouting on rt_ifp.
+ * if @flags contains NHR_REF, do refcouting on rt_ifp and rt_ifa.
  *
  * Returns 0 on success.
  */
@@ -903,10 +903,9 @@ rt_exportinfo(struct rtentry *rt, struct rt_addrinfo *
 	info->rti_flags = rt->rt_flags;
 	info->rti_ifp = rt->rt_ifp;
 	info->rti_ifa = rt->rt_ifa;
-	ifa_ref(info->rti_ifa);
 	if (flags & NHR_REF) {
-		/* Do 'traditional' refcouting */
 		if_ref(info->rti_ifp);
+		ifa_ref(info->rti_ifa);
 	}
 
 	return (0);
@@ -916,8 +915,8 @@ rt_exportinfo(struct rtentry *rt, struct rt_addrinfo *
  * Lookups up route entry for @dst in RIB database for fib @fibnum.
  * Exports entry data to @info using rt_exportinfo().
  *
- * if @flags contains NHR_REF, refcouting is performed on rt_ifp.
- *   All references can be released later by calling rib_free_info()
+ * If @flags contains NHR_REF, refcouting is performed on rt_ifp and rt_ifa.
+ * All references can be released later by calling rib_free_info().
  *
  * Returns 0 on success.
  * Returns ENOENT for lookup failure, ENOMEM for export failure.
@@ -963,6 +962,7 @@ void
 rib_free_info(struct rt_addrinfo *info)
 {
 
+	ifa_free(info->rti_ifa);
 	if_rele(info->rti_ifp);
 }
 
@@ -1631,9 +1631,12 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, stru
 			error = rt_getifa_fib(info, fibnum);
 			if (error)
 				return (error);
+		} else {
+			ifa_ref(info->rti_ifa);
 		}
 		rt = uma_zalloc(V_rtzone, M_NOWAIT);
 		if (rt == NULL) {
+			ifa_free(info->rti_ifa);
 			return (ENOBUFS);
 		}
 		rt->rt_flags = RTF_UP | flags;
@@ -1642,6 +1645,7 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, stru
 		 * Add the gateway. Possibly re-malloc-ing the storage for it.
 		 */
 		if ((error = rt_setgate(rt, dst, gateway)) != 0) {
+			ifa_free(info->rti_ifa);
 			uma_zfree(V_rtzone, rt);
 			return (error);
 		}
@@ -1665,7 +1669,6 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, stru
 		 * examine the ifa and  ifa->ifa_ifp if it so desires.
 		 */
 		ifa = info->rti_ifa;
-		ifa_ref(ifa);
 		rt->rt_ifa = ifa;
 		rt->rt_ifp = ifa->ifa_ifp;
 		rt->rt_weight = 1;
@@ -2108,7 +2111,6 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fi
 		 * Do the actual request
 		 */
 		bzero((caddr_t)&info, sizeof(info));
-		ifa_ref(ifa);
 		info.rti_ifa = ifa;
 		info.rti_flags = flags |
 		    (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;
@@ -2122,7 +2124,6 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fi
 			info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
 		info.rti_info[RTAX_NETMASK] = netmask;
 		error = rtrequest1_fib(cmd, &info, &rt, fibnum);
-
 		if (error == 0 && rt != NULL) {
 			/*
 			 * notify any listening routing agents of the change



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201912270112.xBR1CsAc053618>