Module Name:    src
Committed By:   ozaki-r
Date:           Thu Jul 28 09:03:51 UTC 2016

Modified Files:
        src/sys/netinet: if_arp.c in.c
        src/sys/netinet6: in6.c nd6_nbr.c

Log Message:
Fix panic on adding/deleting IP addresses under network load

Adding and deleting IP addresses aren't serialized with other network
opeartions, e.g., forwarding packets. So if we add or delete an IP
address under network load, a kernel panic may happen on manipulating
network-related shared objects such as rtentry and rtcache.

To avoid such panicks, we still need to hold softnet_lock in in_control
and in6_control that are called via ioctl and do network-related operations
including IP address additions/deletions.

Fix PR kern/51356


To generate a diff of this commit:
cvs rdiff -u -r1.219 -r1.220 src/sys/netinet/if_arp.c
cvs rdiff -u -r1.176 -r1.177 src/sys/netinet/in.c
cvs rdiff -u -r1.211 -r1.212 src/sys/netinet6/in6.c
cvs rdiff -u -r1.125 -r1.126 src/sys/netinet6/nd6_nbr.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/netinet/if_arp.c
diff -u src/sys/netinet/if_arp.c:1.219 src/sys/netinet/if_arp.c:1.220
--- src/sys/netinet/if_arp.c:1.219	Mon Jul 25 04:21:19 2016
+++ src/sys/netinet/if_arp.c	Thu Jul 28 09:03:50 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_arp.c,v 1.219 2016/07/25 04:21:19 ozaki-r Exp $	*/
+/*	$NetBSD: if_arp.c,v 1.220 2016/07/28 09:03:50 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
@@ -68,7 +68,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.219 2016/07/25 04:21:19 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.220 2016/07/28 09:03:50 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -1505,7 +1505,7 @@ static void
 arp_dad_stoptimer(struct dadq *dp)
 {
 
-	callout_halt(&dp->dad_timer_ch, NULL);
+	callout_halt(&dp->dad_timer_ch, softnet_lock);
 }
 
 static void

Index: src/sys/netinet/in.c
diff -u src/sys/netinet/in.c:1.176 src/sys/netinet/in.c:1.177
--- src/sys/netinet/in.c:1.176	Wed Jul 20 03:36:51 2016
+++ src/sys/netinet/in.c	Thu Jul 28 09:03:50 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: in.c,v 1.176 2016/07/20 03:36:51 ozaki-r Exp $	*/
+/*	$NetBSD: in.c,v 1.177 2016/07/28 09:03:50 ozaki-r 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.176 2016/07/20 03:36:51 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.177 2016/07/28 09:03:50 ozaki-r Exp $");
 
 #include "arp.h"
 
@@ -360,8 +360,8 @@ in_len2mask(struct in_addr *mask, u_int 
  * Ifp is 0 if not an interface-specific ioctl.
  */
 /* ARGSUSED */
-int
-in_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
+static int
+in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
 {
 	struct ifreq *ifr = (struct ifreq *)data;
 	struct in_ifaddr *ia = NULL;
@@ -667,6 +667,18 @@ in_control(struct socket *so, u_long cmd
 	return error;
 }
 
+int
+in_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
+{
+	int error;
+
+	mutex_enter(softnet_lock);
+	error = in_control0(so, cmd, data, ifp);
+	mutex_exit(softnet_lock);
+
+	return error;
+}
+
 /* Add ownaddr as loopback rtentry. */
 static void
 in_ifaddlocal(struct ifaddr *ifa)

Index: src/sys/netinet6/in6.c
diff -u src/sys/netinet6/in6.c:1.211 src/sys/netinet6/in6.c:1.212
--- src/sys/netinet6/in6.c:1.211	Wed Jul 20 07:56:10 2016
+++ src/sys/netinet6/in6.c	Thu Jul 28 09:03:50 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: in6.c,v 1.211 2016/07/20 07:56:10 ozaki-r Exp $	*/
+/*	$NetBSD: in6.c,v 1.212 2016/07/28 09:03:50 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.211 2016/07/20 07:56:10 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.212 2016/07/28 09:03:50 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -751,7 +751,9 @@ in6_control(struct socket *so, u_long cm
 	}
 
 	s = splnet();
+	mutex_enter(softnet_lock);
 	error = in6_control1(so , cmd, data, ifp);
+	mutex_exit(softnet_lock);
 	splx(s);
 	return error;
 }

Index: src/sys/netinet6/nd6_nbr.c
diff -u src/sys/netinet6/nd6_nbr.c:1.125 src/sys/netinet6/nd6_nbr.c:1.126
--- src/sys/netinet6/nd6_nbr.c:1.125	Mon Jul 25 04:21:20 2016
+++ src/sys/netinet6/nd6_nbr.c	Thu Jul 28 09:03:50 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: nd6_nbr.c,v 1.125 2016/07/25 04:21:20 ozaki-r Exp $	*/
+/*	$NetBSD: nd6_nbr.c,v 1.126 2016/07/28 09:03:50 ozaki-r Exp $	*/
 /*	$KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $	*/
 
 /*
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.125 2016/07/25 04:21:20 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.126 2016/07/28 09:03:50 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -1077,7 +1077,7 @@ static void
 nd6_dad_stoptimer(struct dadq *dp)
 {
 
-	callout_halt(&dp->dad_timer_ch, NULL);
+	callout_halt(&dp->dad_timer_ch, softnet_lock);
 }
 
 /*

Reply via email to