Source-Changes-HG archive

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

[src/trunk]: src/sys/net Fix locking against myself on ifpromisc



details:   https://anonhg.NetBSD.org/src/rev/cbedb82b7c32
branches:  trunk
changeset: 357962:cbedb82b7c32
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Wed Dec 06 05:59:59 2017 +0000

description:
Fix locking against myself on ifpromisc

vlan_unconfig_locked could be called with holding if_ioctl_lock.

diffstat:

 sys/net/if.c      |  21 ++++++++++++++++-----
 sys/net/if.h      |   3 ++-
 sys/net/if_vlan.c |  26 +++++++++++++++++++++++---
 3 files changed, 41 insertions(+), 9 deletions(-)

diffs (161 lines):

diff -r 81b379dd6e3e -r cbedb82b7c32 sys/net/if.c
--- a/sys/net/if.c      Wed Dec 06 05:11:10 2017 +0000
+++ b/sys/net/if.c      Wed Dec 06 05:59:59 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.c,v 1.401 2017/12/06 05:11:10 ozaki-r Exp $ */
+/*     $NetBSD: if.c,v 1.402 2017/12/06 05:59:59 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.401 2017/12/06 05:11:10 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.402 2017/12/06 05:59:59 ozaki-r Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -2506,12 +2506,12 @@
  * Results are undefined if the "off" and "on" requests are not matched.
  */
 int
-ifpromisc(struct ifnet *ifp, int pswitch)
+ifpromisc_locked(struct ifnet *ifp, int pswitch)
 {
        int pcount, ret = 0;
        short nflags;
 
-       mutex_enter(ifp->if_ioctl_lock);
+       KASSERT(mutex_owned(ifp->if_ioctl_lock));
 
        pcount = ifp->if_pcount;
        if (pswitch) {
@@ -2534,8 +2534,19 @@
                ifp->if_pcount = pcount;
        }
 out:
+       return ret;
+}
+
+int
+ifpromisc(struct ifnet *ifp, int pswitch)
+{
+       int e;
+
+       mutex_enter(ifp->if_ioctl_lock);
+       e = ifpromisc_locked(ifp, pswitch);
        mutex_exit(ifp->if_ioctl_lock);
-       return ret;
+
+       return e;
 }
 
 /*
diff -r 81b379dd6e3e -r cbedb82b7c32 sys/net/if.h
--- a/sys/net/if.h      Wed Dec 06 05:11:10 2017 +0000
+++ b/sys/net/if.h      Wed Dec 06 05:59:59 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.h,v 1.245 2017/12/06 05:11:10 ozaki-r Exp $ */
+/*     $NetBSD: if.h,v 1.246 2017/12/06 05:59:59 ozaki-r Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -1015,6 +1015,7 @@
 extern int (*ifioctl)(struct socket *, u_long, void *, struct lwp *);
 int    ifioctl_common(struct ifnet *, u_long, void *);
 int    ifpromisc(struct ifnet *, int);
+int    ifpromisc_locked(struct ifnet *, int);
 int    if_addr_init(ifnet_t *, struct ifaddr *, bool);
 int    if_do_dad(struct ifnet *);
 int    if_mcast_op(ifnet_t *, const unsigned long, const struct sockaddr *);
diff -r 81b379dd6e3e -r cbedb82b7c32 sys/net/if_vlan.c
--- a/sys/net/if_vlan.c Wed Dec 06 05:11:10 2017 +0000
+++ b/sys/net/if_vlan.c Wed Dec 06 05:59:59 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_vlan.c,v 1.114 2017/12/06 05:11:10 ozaki-r Exp $    */
+/*     $NetBSD: if_vlan.c,v 1.115 2017/12/06 05:59:59 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.114 2017/12/06 05:11:10 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.115 2017/12/06 05:59:59 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -255,6 +255,16 @@
        return e;
 }
 
+static inline int
+vlan_safe_ifpromisc_locked(struct ifnet *ifp, int pswitch)
+{
+       int e;
+       KERNEL_LOCK_UNLESS_NET_MPSAFE();
+       e = ifpromisc_locked(ifp, pswitch);
+       KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
+       return e;
+}
+
 void
 vlanattach(int n)
 {
@@ -387,7 +397,9 @@
        LIST_REMOVE(ifv, ifv_list);
        mutex_exit(&ifv_list.lock);
 
+       mutex_enter(ifp->if_ioctl_lock);
        vlan_unconfig(ifp);
+       mutex_exit(ifp->if_ioctl_lock);
        if_detach(ifp);
 
        psref_target_destroy(&ifv->ifv_mib->ifvm_psref, ifvm_psref_class);
@@ -549,6 +561,8 @@
        struct ifvlan_linkmib *nmib = NULL;
        int error;
 
+       KASSERT(mutex_owned(ifp->if_ioctl_lock));
+
        nmib = kmem_alloc(sizeof(*nmib), KM_SLEEP);
 
        mutex_enter(&ifv->ifv_lock);
@@ -567,6 +581,7 @@
        struct ifvlan_linkmib *omib;
        int error = 0;
 
+       KASSERT(mutex_owned(ifp->if_ioctl_lock));
        KASSERT(mutex_owned(&ifv->ifv_lock));
 
        omib = ifv->ifv_mib;
@@ -635,7 +650,7 @@
 #endif
 
        if ((ifp->if_flags & IFF_PROMISC) != 0)
-               vlan_safe_ifpromisc(ifp, 0);
+               vlan_safe_ifpromisc_locked(ifp, 0);
        if_down(ifp);
        ifp->if_flags &= ~(IFF_UP|IFF_RUNNING);
        ifp->if_capabilities = 0;
@@ -806,6 +821,10 @@
 
        i = 0;
        LIST_FOREACH(ifv, &ifv_list.list, ifv_list) {
+               struct ifnet *ifp = &ifv->ifv_if;
+
+               /* Need if_ioctl_lock that must be held before ifv_lock. */
+               mutex_enter(ifp->if_ioctl_lock);
                mutex_enter(&ifv->ifv_lock);
                if (ifv->ifv_mib->ifvm_p == p) {
                        KASSERTMSG(i < cnt, "no memory for unconfig, parent=%s",
@@ -818,6 +837,7 @@
 
                }
                mutex_exit(&ifv->ifv_lock);
+               mutex_exit(ifp->if_ioctl_lock);
        }
 
        mutex_exit(&ifv_list.lock);



Home | Main Index | Thread Index | Old Index