Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 1 Feb 2019 09:07:27 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r343649 - stable/12/sys/netinet6
Message-ID:  <201902010907.x1197RV8011426@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Fri Feb  1 09:07:27 2019
New Revision: 343649
URL: https://svnweb.freebsd.org/changeset/base/343649

Log:
  MFC r343394:
  When detaching a network interface drain the workqueue freeing the inm's
  because the destructor will access the if_ioctl() callback in the ifnet
  pointer which is about to be freed. This prevents use-after-free.
  
  PR:			233535
  Differential Revision:	https://reviews.freebsd.org/D18887
  Reviewed by:		bz (net)
  Tested by:		ae
  Sponsored by:		Mellanox Technologies

Modified:
  stable/12/sys/netinet6/in6_ifattach.c
  stable/12/sys/netinet6/in6_mcast.c
  stable/12/sys/netinet6/in6_var.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/netinet6/in6_ifattach.c
==============================================================================
--- stable/12/sys/netinet6/in6_ifattach.c	Fri Feb  1 09:06:40 2019	(r343648)
+++ stable/12/sys/netinet6/in6_ifattach.c	Fri Feb  1 09:07:27 2019	(r343649)
@@ -882,6 +882,13 @@ in6_purgemaddrs(struct ifnet *ifp)
 	IN6_MULTI_LIST_UNLOCK();
 	IN6_MULTI_UNLOCK();
 	in6m_release_list_deferred(&purgeinms);
+
+	/*
+	 * Make sure all multicast deletions invoking if_ioctl() are
+	 * completed before returning. Else we risk accessing a freed
+	 * ifnet structure pointer.
+	 */
+	in6m_release_wait();
 }
 
 void

Modified: stable/12/sys/netinet6/in6_mcast.c
==============================================================================
--- stable/12/sys/netinet6/in6_mcast.c	Fri Feb  1 09:06:40 2019	(r343648)
+++ stable/12/sys/netinet6/in6_mcast.c	Fri Feb  1 09:07:27 2019	(r343649)
@@ -585,6 +585,14 @@ in6m_release_list_deferred(struct in6_multi_head *inmh
 }
 
 void
+in6m_release_wait(void)
+{
+
+	/* Wait for all jobs to complete. */
+	gtaskqueue_drain_all(free_gtask.gt_taskqueue);
+}
+
+void
 in6m_disconnect(struct in6_multi *inm)
 {
 	struct ifnet *ifp;

Modified: stable/12/sys/netinet6/in6_var.h
==============================================================================
--- stable/12/sys/netinet6/in6_var.h	Fri Feb  1 09:06:40 2019	(r343648)
+++ stable/12/sys/netinet6/in6_var.h	Fri Feb  1 09:07:27 2019	(r343649)
@@ -810,6 +810,7 @@ void	in6m_print(const struct in6_multi *);
 int	in6m_record_source(struct in6_multi *, const struct in6_addr *);
 void	in6m_release_deferred(struct in6_multi *);
 void	in6m_release_list_deferred(struct in6_multi_head *);
+void	in6m_release_wait(void);
 void	ip6_freemoptions(struct ip6_moptions *);
 int	ip6_getmoptions(struct inpcb *, struct sockopt *);
 int	ip6_setmoptions(struct inpcb *, struct sockopt *);



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