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: