Author: thompsa
Date: Thu Apr 12 01:07:17 2012
New Revision: 234163
URL: http://svn.freebsd.org/changeset/base/234163

Log:
  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)

Modified:
  head/sys/net/if_lagg.c

Modified: head/sys/net/if_lagg.c
==============================================================================
--- head/sys/net/if_lagg.c      Thu Apr 12 00:59:30 2012        (r234162)
+++ head/sys/net/if_lagg.c      Thu Apr 12 01:07:17 2012        (r234163)
@@ -950,11 +950,11 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd
                        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
                        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
                                        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
                                return (error);
                        }
                }
+               LAGG_WUNLOCK(sc);
                error = EPROTONOSUPPORT;
                break;
        case SIOCGLAGGFLAGS:
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to