Module Name:    src
Committed By:   ozaki-r
Date:           Thu Mar  2 05:27:39 UTC 2017

Modified Files:
        src/sys/netinet6: in6.c in6_var.h mld6.c

Log Message:
Protect ia6_memberships by in6_ifaddr_lock


To generate a diff of this commit:
cvs rdiff -u -r1.241 -r1.242 src/sys/netinet6/in6.c
cvs rdiff -u -r1.94 -r1.95 src/sys/netinet6/in6_var.h
cvs rdiff -u -r1.85 -r1.86 src/sys/netinet6/mld6.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netinet6/in6.c
diff -u src/sys/netinet6/in6.c:1.241 src/sys/netinet6/in6.c:1.242
--- src/sys/netinet6/in6.c:1.241	Wed Mar  1 03:02:35 2017
+++ src/sys/netinet6/in6.c	Thu Mar  2 05:27:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6.c,v 1.241 2017/03/01 03:02:35 ozaki-r Exp $	*/
+/*	$NetBSD: in6.c,v 1.242 2017/03/02 05:27:39 ozaki-r Exp $	*/
 /*	$KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $	*/
 
 /*
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.241 2017/03/01 03:02:35 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.242 2017/03/02 05:27:39 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -825,7 +825,9 @@ in6_join_mcastgroups(struct in6_aliasreq
 		    IN6_PRINT(ip6buf, &llsol), if_name(ifp), error);
 		goto out;
 	}
+	mutex_enter(&in6_ifaddr_lock);
 	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
+	mutex_exit(&in6_ifaddr_lock);
 	*in6m_sol = imm->i6mm_maddr;
 
 	sockaddr_in6_init(&mltmask, &in6mask32, 0, 0, 0);
@@ -887,7 +889,9 @@ in6_join_mcastgroups(struct in6_aliasreq
 		    if_name(ifp), error);
 		goto out;
 	}
+	mutex_enter(&in6_ifaddr_lock);
 	LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
+	mutex_exit(&in6_ifaddr_lock);
 
 	/*
 	 * join node information group address
@@ -910,7 +914,9 @@ in6_join_mcastgroups(struct in6_aliasreq
 		    if_name(ifp), error);
 		/* XXX not very fatal, go on... */
 	} else {
+		mutex_enter(&in6_ifaddr_lock);
 		LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
+		mutex_exit(&in6_ifaddr_lock);
 	}
 
 
@@ -967,7 +973,9 @@ in6_join_mcastgroups(struct in6_aliasreq
 		    if_name(ifp), error);
 		goto out;
 	} else {
+		mutex_enter(&in6_ifaddr_lock);
 		LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
+		mutex_exit(&in6_ifaddr_lock);
 	}
 	return 0;
 
@@ -1372,10 +1380,14 @@ in6_purgeaddr(struct ifaddr *ifa)
 	/*
 	 * leave from multicast groups we have joined for the interface
 	 */
+	mutex_enter(&in6_ifaddr_lock);
 	while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) {
 		LIST_REMOVE(imm, i6mm_chain);
+		mutex_exit(&in6_ifaddr_lock);
 		in6_leavegroup(imm);
+		mutex_enter(&in6_ifaddr_lock);
 	}
+	mutex_exit(&in6_ifaddr_lock);
 
 	in6_unlink_ifa(ia, ifp);
 }
@@ -1427,6 +1439,23 @@ in6_purgeif(struct ifnet *ifp)
 	in6_ifdetach(ifp);
 }
 
+void
+in6_purge_mcast_references(struct in6_multi *in6m)
+{
+	struct	in6_ifaddr *ia;
+
+	mutex_enter(&in6_ifaddr_lock);
+	IN6_ADDRLIST_WRITER_FOREACH(ia) {
+		struct in6_multi_mship *imm;
+		/* XXX imm isn't safe? */
+		LIST_FOREACH(imm, &ia->ia6_memberships, i6mm_chain) {
+			if (imm->i6mm_maddr == in6m)
+				imm->i6mm_maddr = NULL;
+		}
+	}
+	mutex_exit(&in6_ifaddr_lock);
+}
+
 /*
  * SIOC[GAD]LIFADDR.
  *	SIOCGLIFADDR: get first address. (?)

Index: src/sys/netinet6/in6_var.h
diff -u src/sys/netinet6/in6_var.h:1.94 src/sys/netinet6/in6_var.h:1.95
--- src/sys/netinet6/in6_var.h:1.94	Wed Mar  1 08:54:12 2017
+++ src/sys/netinet6/in6_var.h	Thu Mar  2 05:27:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6_var.h,v 1.94 2017/03/01 08:54:12 ozaki-r Exp $	*/
+/*	$NetBSD: in6_var.h,v 1.95 2017/03/02 05:27:39 ozaki-r Exp $	*/
 /*	$KAME: in6_var.h,v 1.81 2002/06/08 11:16:51 itojun Exp $	*/
 
 /*
@@ -716,6 +716,7 @@ int	in6_matchlen(struct in6_addr *, stru
 int	in6_are_prefix_equal(struct in6_addr *, struct in6_addr *, int);
 void	in6_prefixlen2mask(struct in6_addr *, int);
 void	in6_purgeprefix(struct ifnet *);
+void	in6_purge_mcast_references(struct in6_multi *);
 
 int	ip6flow_fastforward(struct mbuf **); /* IPv6 fast forward routine */
 

Index: src/sys/netinet6/mld6.c
diff -u src/sys/netinet6/mld6.c:1.85 src/sys/netinet6/mld6.c:1.86
--- src/sys/netinet6/mld6.c:1.85	Wed Mar  1 09:09:37 2017
+++ src/sys/netinet6/mld6.c	Thu Mar  2 05:27:39 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: mld6.c,v 1.85 2017/03/01 09:09:37 ozaki-r Exp $	*/
+/*	$NetBSD: mld6.c,v 1.86 2017/03/02 05:27:39 ozaki-r Exp $	*/
 /*	$KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $	*/
 
 /*
@@ -102,7 +102,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.85 2017/03/01 09:09:37 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.86 2017/03/02 05:27:39 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -788,9 +788,7 @@ out:
 static void
 in6m_destroy(struct in6_multi *in6m)
 {
-	struct	in6_ifaddr *ia;
 	struct sockaddr_in6 sin6;
-	int s;
 
 	KASSERT(rw_write_held(&in6_multilock));
 	KASSERT(in6m->in6m_refcount == 0);
@@ -810,15 +808,7 @@ in6m_destroy(struct in6_multi *in6m)
 	 * Delete all references of this multicasting group from
 	 * the membership arrays
 	 */
-	s = pserialize_read_enter();
-	IN6_ADDRLIST_READER_FOREACH(ia) {
-		struct in6_multi_mship *imm;
-		LIST_FOREACH(imm, &ia->ia6_memberships, i6mm_chain) {
-			if (imm->i6mm_maddr == in6m)
-				imm->i6mm_maddr = NULL;
-		}
-	}
-	pserialize_read_exit(s);
+	in6_purge_mcast_references(in6m);
 
 	/*
 	 * Notify the network driver to update its multicast

Reply via email to