Author: hselasky
Date: Thu Jan 24 08:25:02 2019
New Revision: 343394
URL: https://svnweb.freebsd.org/changeset/base/343394

Log:
  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
  MFC after:            1 week
  Sponsored by:         Mellanox Technologies

Modified:
  head/sys/netinet6/in6_ifattach.c
  head/sys/netinet6/in6_mcast.c
  head/sys/netinet6/in6_var.h

Modified: head/sys/netinet6/in6_ifattach.c
==============================================================================
--- head/sys/netinet6/in6_ifattach.c    Thu Jan 24 08:18:02 2019        
(r343393)
+++ head/sys/netinet6/in6_ifattach.c    Thu Jan 24 08:25:02 2019        
(r343394)
@@ -884,6 +884,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: head/sys/netinet6/in6_mcast.c
==============================================================================
--- head/sys/netinet6/in6_mcast.c       Thu Jan 24 08:18:02 2019        
(r343393)
+++ head/sys/netinet6/in6_mcast.c       Thu Jan 24 08:25:02 2019        
(r343394)
@@ -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: head/sys/netinet6/in6_var.h
==============================================================================
--- head/sys/netinet6/in6_var.h Thu Jan 24 08:18:02 2019        (r343393)
+++ head/sys/netinet6/in6_var.h Thu Jan 24 08:25:02 2019        (r343394)
@@ -811,6 +811,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 *);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to