Module Name:    src
Committed By:   knakahara
Date:           Tue Dec  6 07:01:47 UTC 2016

Modified Files:
        src/sys/net: if_spppsubr.c
        src/sys/netinet: in.c in_var.h

Log Message:
add API to manipulate ifa->ia_hash and ia_hash_pslist_entry, and fix 
ia_hash_pslist_entry race by using them.

in_ifaddr_lock is required before writing ifa->ia_hash and
ia_hash_pslist_entry to serialize writer processings.

reviewed by ozaki-r@n.o.


To generate a diff of this commit:
cvs rdiff -u -r1.161 -r1.162 src/sys/net/if_spppsubr.c
cvs rdiff -u -r1.188 -r1.189 src/sys/netinet/in.c
cvs rdiff -u -r1.89 -r1.90 src/sys/netinet/in_var.h

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

Modified files:

Index: src/sys/net/if_spppsubr.c
diff -u src/sys/net/if_spppsubr.c:1.161 src/sys/net/if_spppsubr.c:1.162
--- src/sys/net/if_spppsubr.c:1.161	Thu Dec  1 02:30:54 2016
+++ src/sys/net/if_spppsubr.c	Tue Dec  6 07:01:47 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_spppsubr.c,v 1.161 2016/12/01 02:30:54 knakahara Exp $	 */
+/*	$NetBSD: if_spppsubr.c,v 1.162 2016/12/06 07:01:47 knakahara Exp $	 */
 
 /*
  * Synchronous PPP/Cisco link level subroutines.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.161 2016/12/01 02:30:54 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.162 2016/12/06 07:01:47 knakahara Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -4921,19 +4921,11 @@ sppp_set_ip_addrs_work(struct work *wk, 
 				sp->ipcp.saved_hisaddr = dest->sin_addr.s_addr;
 		}
 
-		LIST_REMOVE(ifatoia(ifa), ia_hash);
-		IN_ADDRHASH_WRITER_REMOVE(ifatoia(ifa));
-#ifdef NET_MPSAFE
-		pserialize_perform(in_ifaddrhash_psz);
-#endif
-		IN_ADDRHASH_ENTRY_DESTROY(ifatoia(ifa));
+		in_addrhash_remove(ifatoia(ifa));
 
 		error = in_ifinit(ifp, ifatoia(ifa), &new_sin, &new_dst, 0);
 
-		IN_ADDRHASH_ENTRY_INIT(ifatoia(ifa));
-		LIST_INSERT_HEAD(&IN_IFADDR_HASH(ifatoia(ifa)->ia_addr.sin_addr.s_addr),
-		    ifatoia(ifa), ia_hash);
-		IN_ADDRHASH_WRITER_INSERT_HEAD(ifatoia(ifa));
+		in_addrhash_insert(ifatoia(ifa));
 
 		if (debug && error)
 		{
@@ -5012,19 +5004,11 @@ sppp_clear_ip_addrs_work(struct work *wk
 		if (sp->ipcp.flags & IPCP_HISADDR_DYN)
 			new_dst.sin_addr.s_addr = sp->ipcp.saved_hisaddr;
 
-		LIST_REMOVE(ifatoia(ifa), ia_hash);
-		IN_ADDRHASH_WRITER_REMOVE(ifatoia(ifa));
-#ifdef NET_MPSAFE
-		pserialize_perform(in_ifaddrhash_psz);
-#endif
-		IN_ADDRHASH_ENTRY_DESTROY(ifatoia(ifa));
+		in_addrhash_remove(ifatoia(ifa));
 
 		error = in_ifinit(ifp, ifatoia(ifa), &new_sin, &new_dst, 0);
 
-		IN_ADDRHASH_ENTRY_INIT(ifatoia(ifa));
-		LIST_INSERT_HEAD(&IN_IFADDR_HASH(ifatoia(ifa)->ia_addr.sin_addr.s_addr),
-		    ifatoia(ifa), ia_hash);
-		IN_ADDRHASH_WRITER_INSERT_HEAD(ifatoia(ifa));
+		in_addrhash_insert(ifatoia(ifa));
 
 		if (debug && error)
 		{

Index: src/sys/netinet/in.c
diff -u src/sys/netinet/in.c:1.188 src/sys/netinet/in.c:1.189
--- src/sys/netinet/in.c:1.188	Fri Nov 18 10:38:55 2016
+++ src/sys/netinet/in.c	Tue Dec  6 07:01:47 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: in.c,v 1.188 2016/11/18 10:38:55 knakahara Exp $	*/
+/*	$NetBSD: in.c,v 1.189 2016/12/06 07:01:47 knakahara Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.188 2016/11/18 10:38:55 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.189 2016/12/06 07:01:47 knakahara Exp $");
 
 #include "arp.h"
 
@@ -149,6 +149,9 @@ static void	in_len2mask(struct in_addr *
 static int	in_lifaddr_ioctl(struct socket *, u_long, void *,
 	struct ifnet *);
 
+static void	in_addrhash_insert_locked(struct in_ifaddr *);
+static void	in_addrhash_remove_locked(struct in_ifaddr *);
+
 static int	in_addprefix(struct in_ifaddr *, int);
 static void	in_scrubaddr(struct in_ifaddr *);
 static int	in_scrubprefix(struct in_ifaddr *);
@@ -598,14 +601,7 @@ in_control0(struct socket *so, u_long cm
 
 	case SIOCSIFADDR:
 		if (!newifaddr) {
-			mutex_enter(&in_ifaddr_lock);
-			LIST_REMOVE(ia, ia_hash);
-			IN_ADDRHASH_WRITER_REMOVE(ia);
-			mutex_exit(&in_ifaddr_lock);
-#ifdef NET_MPSAFE
-			pserialize_perform(in_ifaddrhash_psz);
-#endif
-			IN_ADDRHASH_ENTRY_DESTROY(ia);
+			in_addrhash_remove(ia);
 			need_reinsert = true;
 		}
 		error = in_ifinit(ifp, ia, satocsin(ifreq_getaddr(cmd, ifr)),
@@ -619,14 +615,7 @@ in_control0(struct socket *so, u_long cm
 		ia->ia_sockmask = *satocsin(ifreq_getaddr(cmd, ifr));
 		ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
 		if (!newifaddr) {
-			mutex_enter(&in_ifaddr_lock);
-			LIST_REMOVE(ia, ia_hash);
-			IN_ADDRHASH_WRITER_REMOVE(ia);
-			mutex_exit(&in_ifaddr_lock);
-#ifdef NET_MPSAFE
-			pserialize_perform(in_ifaddrhash_psz);
-#endif
-			IN_ADDRHASH_ENTRY_DESTROY(ia);
+			in_addrhash_remove(ia);
 			need_reinsert = true;
 		}
 		error = in_ifinit(ifp, ia, NULL, NULL, 0);
@@ -649,14 +638,7 @@ in_control0(struct socket *so, u_long cm
 		if (ifra->ifra_addr.sin_family == AF_INET &&
 		    (hostIsNew || maskIsNew)) {
 			if (!newifaddr) {
-				mutex_enter(&in_ifaddr_lock);
-				LIST_REMOVE(ia, ia_hash);
-				IN_ADDRHASH_WRITER_REMOVE(ia);
-				mutex_exit(&in_ifaddr_lock);
-#ifdef NET_MPSAFE
-				pserialize_perform(in_ifaddrhash_psz);
-#endif
-				IN_ADDRHASH_ENTRY_DESTROY(ia);
+				in_addrhash_remove(ia);
 				need_reinsert = true;
 			}
 			error = in_ifinit(ifp, ia, &ifra->ifra_addr,
@@ -715,17 +697,10 @@ in_control0(struct socket *so, u_long cm
 		mutex_enter(&in_ifaddr_lock);
 		TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_list);
 		IN_ADDRLIST_WRITER_INSERT_TAIL(ia);
-		LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr),
-		    ia, ia_hash);
-		IN_ADDRHASH_WRITER_INSERT_HEAD(ia);
+		in_addrhash_insert_locked(ia);
 		mutex_exit(&in_ifaddr_lock);
 	} else if (need_reinsert) {
-		mutex_enter(&in_ifaddr_lock);
-		LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr),
-		    ia, ia_hash);
-		IN_ADDRHASH_ENTRY_INIT(ia);
-		IN_ADDRHASH_WRITER_INSERT_HEAD(ia);
-		mutex_exit(&in_ifaddr_lock);
+		in_addrhash_insert(ia);
 	}
 
 	if (error == 0) {
@@ -851,8 +826,7 @@ in_purgeaddr(struct ifaddr *ifa)
 	in_scrubaddr(ia);
 
 	mutex_enter(&in_ifaddr_lock);
-	LIST_REMOVE(ia, ia_hash);
-	IN_ADDRHASH_WRITER_REMOVE(ia);
+	in_addrhash_remove_locked(ia);
 	TAILQ_REMOVE(&in_ifaddrhead, ia, ia_list);
 	IN_ADDRLIST_WRITER_REMOVE(ia);
 	ifa_remove(ifp, &ia->ia_ifa);
@@ -867,6 +841,50 @@ in_purgeaddr(struct ifaddr *ifa)
 	in_setmaxmtu();
 }
 
+static void
+in_addrhash_insert_locked(struct in_ifaddr *ia)
+{
+
+	KASSERT(mutex_owned(&in_ifaddr_lock));
+
+	LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia,
+	    ia_hash);
+	IN_ADDRHASH_ENTRY_INIT(ia);
+	IN_ADDRHASH_WRITER_INSERT_HEAD(ia);
+}
+
+void
+in_addrhash_insert(struct in_ifaddr *ia)
+{
+
+	mutex_enter(&in_ifaddr_lock);
+	in_addrhash_insert_locked(ia);
+	mutex_exit(&in_ifaddr_lock);
+}
+
+static void
+in_addrhash_remove_locked(struct in_ifaddr *ia)
+{
+
+	KASSERT(mutex_owned(&in_ifaddr_lock));
+
+	LIST_REMOVE(ia, ia_hash);
+	IN_ADDRHASH_WRITER_REMOVE(ia);
+}
+
+void
+in_addrhash_remove(struct in_ifaddr *ia)
+{
+
+	mutex_enter(&in_ifaddr_lock);
+	in_addrhash_remove_locked(ia);
+	mutex_exit(&in_ifaddr_lock);
+#ifdef NET_MPSAFE
+	pserialize_perform(in_ifaddrhash_psz);
+#endif
+	IN_ADDRHASH_ENTRY_DESTROY(ia);
+}
+
 void
 in_purgeif(struct ifnet *ifp)		/* MUST be called at splsoftnet() */
 {

Index: src/sys/netinet/in_var.h
diff -u src/sys/netinet/in_var.h:1.89 src/sys/netinet/in_var.h:1.90
--- src/sys/netinet/in_var.h:1.89	Fri Nov 18 10:38:55 2016
+++ src/sys/netinet/in_var.h	Tue Dec  6 07:01:47 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: in_var.h,v 1.89 2016/11/18 10:38:55 knakahara Exp $	*/
+/*	$NetBSD: in_var.h,v 1.90 2016/12/06 07:01:47 knakahara Exp $	*/
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -420,6 +420,8 @@ const char *in_fmtaddr(struct in_addr);
 int	in_control(struct socket *, u_long, void *, struct ifnet *);
 void	in_purgeaddr(struct ifaddr *);
 void	in_purgeif(struct ifnet *);
+void	in_addrhash_insert(struct in_ifaddr *);
+void	in_addrhash_remove(struct in_ifaddr *);
 int	ipflow_fastforward(struct mbuf *);
 
 struct ipid_state;

Reply via email to