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;