Module Name:    src
Committed By:   ozaki-r
Date:           Wed Dec  6 08:12:54 UTC 2017

Modified Files:
        src/sys/net: if.c if.h if_vlan.c

Log Message:
Ensure to hold if_ioctl_lock on if_up and if_down

One exception for if_down is if_detach; in the case the lock isn't needed
because it's guaranteed that no other one can access ifp at that point.


To generate a diff of this commit:
cvs rdiff -u -r1.402 -r1.403 src/sys/net/if.c
cvs rdiff -u -r1.246 -r1.247 src/sys/net/if.h
cvs rdiff -u -r1.116 -r1.117 src/sys/net/if_vlan.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/net/if.c
diff -u src/sys/net/if.c:1.402 src/sys/net/if.c:1.403
--- src/sys/net/if.c:1.402	Wed Dec  6 05:59:59 2017
+++ src/sys/net/if.c	Wed Dec  6 08:12:54 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.c,v 1.402 2017/12/06 05:59:59 ozaki-r Exp $	*/
+/*	$NetBSD: if.c,v 1.403 2017/12/06 08:12:54 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.402 2017/12/06 05:59:59 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.403 2017/12/06 08:12:54 ozaki-r Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -209,6 +209,9 @@ static int if_transmit(struct ifnet *, s
 static int if_clone_create(const char *);
 static int if_clone_destroy(const char *);
 static void if_link_state_change_si(void *);
+static void if_up_locked(struct ifnet *);
+static void _if_down(struct ifnet *);
+static void if_down_deactivated(struct ifnet *);
 
 struct if_percpuq {
 	struct ifnet	*ipq_ifp;
@@ -1333,7 +1336,7 @@ if_detach(struct ifnet *ifp)
 	/*
 	 * Do an if_down() to give protocols a chance to do something.
 	 */
-	if_down(ifp);
+	if_down_deactivated(ifp);
 
 #ifdef ALTQ
 	if (ALTQ_IS_ENABLED(&ifp->if_snd))
@@ -2400,13 +2403,8 @@ p2p_rtrequest(int req, struct rtentry *r
 	pserialize_read_exit(s);
 }
 
-/*
- * Mark an interface down and notify protocols of
- * the transition.
- * NOTE: must be called at splsoftnet or equivalent.
- */
-void
-if_down(struct ifnet *ifp)
+static void
+_if_down(struct ifnet *ifp)
 {
 	struct ifaddr *ifa;
 	struct domain *dp;
@@ -2442,19 +2440,50 @@ if_down(struct ifnet *ifp)
 	}
 }
 
+static void
+if_down_deactivated(struct ifnet *ifp)
+{
+
+	KASSERT(if_is_deactivated(ifp));
+	_if_down(ifp);
+}
+
+void
+if_down_locked(struct ifnet *ifp)
+{
+
+	KASSERT(mutex_owned(ifp->if_ioctl_lock));
+	_if_down(ifp);
+}
+
 /*
- * Mark an interface up and notify protocols of
+ * Mark an interface down and notify protocols of
  * the transition.
  * NOTE: must be called at splsoftnet or equivalent.
  */
 void
-if_up(struct ifnet *ifp)
+if_down(struct ifnet *ifp)
+{
+
+	mutex_enter(ifp->if_ioctl_lock);
+	if_down_locked(ifp);
+	mutex_exit(ifp->if_ioctl_lock);
+}
+
+/*
+ * Must be called with holding if_ioctl_lock.
+ */
+static void
+if_up_locked(struct ifnet *ifp)
 {
 #ifdef notyet
 	struct ifaddr *ifa;
 #endif
 	struct domain *dp;
 
+	KASSERT(mutex_owned(ifp->if_ioctl_lock));
+
+	KASSERT(!if_is_deactivated(ifp));
 	ifp->if_flags |= IFF_UP;
 	nanotime(&ifp->if_lastchange);
 #ifdef notyet
@@ -2500,6 +2529,20 @@ if_slowtimo(void *arg)
 }
 
 /*
+ * Mark an interface up and notify protocols of
+ * the transition.
+ * NOTE: must be called at splsoftnet or equivalent.
+ */
+void
+if_up(struct ifnet *ifp)
+{
+
+	mutex_enter(ifp->if_ioctl_lock);
+	if_up_locked(ifp);
+	mutex_exit(ifp->if_ioctl_lock);
+}
+
+/*
  * Set/clear promiscuous mode on interface ifp based on the truth value
  * of pswitch.  The calls are reference counted so that only the first
  * "on" request actually has an effect, as does the final "off" request.
@@ -2789,12 +2832,12 @@ ifioctl_common(struct ifnet *ifp, u_long
 		KERNEL_LOCK_IF_IFP_MPSAFE(ifp);
 		if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
 			s = splsoftnet();
-			if_down(ifp);
+			if_down_locked(ifp);
 			splx(s);
 		}
 		if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
 			s = splsoftnet();
-			if_up(ifp);
+			if_up_locked(ifp);
 			splx(s);
 		}
 		KERNEL_UNLOCK_IF_IFP_MPSAFE(ifp);
@@ -3103,7 +3146,7 @@ doifioctl(struct socket *so, u_long cmd,
 	if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
 		if ((ifp->if_flags & IFF_UP) != 0) {
 			int s = splsoftnet();
-			if_up(ifp);
+			if_up_locked(ifp);
 			splx(s);
 		}
 	}

Index: src/sys/net/if.h
diff -u src/sys/net/if.h:1.246 src/sys/net/if.h:1.247
--- src/sys/net/if.h:1.246	Wed Dec  6 05:59:59 2017
+++ src/sys/net/if.h	Wed Dec  6 08:12:54 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.h,v 1.246 2017/12/06 05:59:59 ozaki-r Exp $	*/
+/*	$NetBSD: if.h,v 1.247 2017/12/06 08:12:54 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -1006,6 +1006,7 @@ bool	if_is_deactivated(const struct ifne
 void	if_purgeaddrs(struct ifnet *, int, void (*)(struct ifaddr *));
 void	if_detach(struct ifnet *);
 void	if_down(struct ifnet *);
+void	if_down_locked(struct ifnet *);
 void	if_link_state_change(struct ifnet *, int);
 void	if_link_state_change_softint(struct ifnet *, int);
 void	if_up(struct ifnet *);

Index: src/sys/net/if_vlan.c
diff -u src/sys/net/if_vlan.c:1.116 src/sys/net/if_vlan.c:1.117
--- src/sys/net/if_vlan.c:1.116	Wed Dec  6 07:40:16 2017
+++ src/sys/net/if_vlan.c	Wed Dec  6 08:12:54 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_vlan.c,v 1.116 2017/12/06 07:40:16 ozaki-r Exp $	*/
+/*	$NetBSD: if_vlan.c,v 1.117 2017/12/06 08:12:54 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
@@ -78,7 +78,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.116 2017/12/06 07:40:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.117 2017/12/06 08:12:54 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -653,7 +653,7 @@ vlan_unconfig_locked(struct ifvlan *ifv,
 
 	if ((ifp->if_flags & IFF_PROMISC) != 0)
 		vlan_safe_ifpromisc_locked(ifp, 0);
-	if_down(ifp);
+	if_down_locked(ifp);
 	ifp->if_capabilities = 0;
 	mutex_enter(&ifv->ifv_lock);
 done:

Reply via email to