Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Fix panic on adding/deleting IP addresses under network ...



details:   https://anonhg.NetBSD.org/src/rev/f3e1b036fceb
branches:  trunk
changeset: 816832:f3e1b036fceb
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Thu Jul 28 09:03:50 2016 +0000

description:
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

diffstat:

 sys/netinet/if_arp.c   |   6 +++---
 sys/netinet/in.c       |  20 ++++++++++++++++----
 sys/netinet6/in6.c     |   6 ++++--
 sys/netinet6/nd6_nbr.c |   6 +++---
 4 files changed, 26 insertions(+), 12 deletions(-)

diffs (130 lines):

diff -r a6b7dcece7a5 -r f3e1b036fceb sys/netinet/if_arp.c
--- a/sys/netinet/if_arp.c      Thu Jul 28 08:24:58 2016 +0000
+++ b/sys/netinet/if_arp.c      Thu Jul 28 09:03:50 2016 +0000
@@ -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 @@
 arp_dad_stoptimer(struct dadq *dp)
 {
 
-       callout_halt(&dp->dad_timer_ch, NULL);
+       callout_halt(&dp->dad_timer_ch, softnet_lock);
 }
 
 static void
diff -r a6b7dcece7a5 -r f3e1b036fceb sys/netinet/in.c
--- a/sys/netinet/in.c  Thu Jul 28 08:24:58 2016 +0000
+++ b/sys/netinet/in.c  Thu Jul 28 09:03:50 2016 +0000
@@ -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 @@
  * 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 @@
        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)
diff -r a6b7dcece7a5 -r f3e1b036fceb sys/netinet6/in6.c
--- a/sys/netinet6/in6.c        Thu Jul 28 08:24:58 2016 +0000
+++ b/sys/netinet6/in6.c        Thu Jul 28 09:03:50 2016 +0000
@@ -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 @@
        }
 
        s = splnet();
+       mutex_enter(softnet_lock);
        error = in6_control1(so , cmd, data, ifp);
+       mutex_exit(softnet_lock);
        splx(s);
        return error;
 }
diff -r a6b7dcece7a5 -r f3e1b036fceb sys/netinet6/nd6_nbr.c
--- a/sys/netinet6/nd6_nbr.c    Thu Jul 28 08:24:58 2016 +0000
+++ b/sys/netinet6/nd6_nbr.c    Thu Jul 28 09:03:50 2016 +0000
@@ -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 @@
 nd6_dad_stoptimer(struct dadq *dp)
 {
 
-       callout_halt(&dp->dad_timer_ch, NULL);
+       callout_halt(&dp->dad_timer_ch, softnet_lock);
 }
 
 /*



Home | Main Index | Thread Index | Old Index