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/591c4102234c
branches:  trunk
changeset: 346690:591c4102234c
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 b25a1874493c -r 591c4102234c 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 b25a1874493c -r 591c4102234c 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 b25a1874493c -r 591c4102234c 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 b25a1874493c -r 591c4102234c 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