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