aboutsummaryrefslogtreecommitdiff
path: root/sys/net/if_lagg.c
diff options
context:
space:
mode:
authorAndrew Thompson <thompsa@FreeBSD.org>2012-04-12 01:07:17 +0000
committerAndrew Thompson <thompsa@FreeBSD.org>2012-04-12 01:07:17 +0000
commitb517176ad9c080a4370d93b255cc3fa2d6b0504b (patch)
tree74abc7b733a9492c1fde5128c581ec0822509222 /sys/net/if_lagg.c
parentdd4b1ae7017ad27efba85ccbdc6c4f8fc7a5b769 (diff)
downloadsrc-b517176ad9c080a4370d93b255cc3fa2d6b0504b.tar.gz
src-b517176ad9c080a4370d93b255cc3fa2d6b0504b.zip
Set the proto to LAGG_PROTO_NONE before calling the detach routine so packets
are discarded, this is an issue because lacp drops the lock which may allow network threads to access freed memory. Expand the lock coverage so the detach/attach happen atomically. Submitted by: Andrew Boyer (earlier version)
Notes
Notes: svn path=/head/; revision=234163
Diffstat (limited to 'sys/net/if_lagg.c')
-rw-r--r--sys/net/if_lagg.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index ba19c52dadad..b7beb86a9b84 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -950,11 +950,11 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = EPROTONOSUPPORT;
break;
}
+ LAGG_WLOCK(sc);
if (sc->sc_proto != LAGG_PROTO_NONE) {
- LAGG_WLOCK(sc);
- error = sc->sc_detach(sc);
- /* Reset protocol and pointers */
+ /* Reset protocol first in case detach unlocks */
sc->sc_proto = LAGG_PROTO_NONE;
+ error = sc->sc_detach(sc);
sc->sc_detach = NULL;
sc->sc_start = NULL;
sc->sc_input = NULL;
@@ -966,10 +966,14 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
sc->sc_lladdr = NULL;
sc->sc_req = NULL;
sc->sc_portreq = NULL;
- LAGG_WUNLOCK(sc);
+ } else if (sc->sc_input != NULL) {
+ /* Still detaching */
+ error = EBUSY;
}
- if (error != 0)
+ if (error != 0) {
+ LAGG_WUNLOCK(sc);
break;
+ }
for (int i = 0; i < (sizeof(lagg_protos) /
sizeof(lagg_protos[0])); i++) {
if (lagg_protos[i].ti_proto == ra->ra_proto) {
@@ -977,7 +981,6 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
printf("%s: using proto %u\n",
sc->sc_ifname,
lagg_protos[i].ti_proto);
- LAGG_WLOCK(sc);
sc->sc_proto = lagg_protos[i].ti_proto;
if (sc->sc_proto != LAGG_PROTO_NONE)
error = lagg_protos[i].ti_attach(sc);
@@ -985,6 +988,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
return (error);
}
}
+ LAGG_WUNLOCK(sc);
error = EPROTONOSUPPORT;
break;
case SIOCGLAGGFLAGS: