Author: markj
Date: Tue Dec 17 21:34:38 2019
New Revision: 355864
URL: https://svnweb.freebsd.org/changeset/base/355864

Log:
  an(4): Require privileges for all SIOCGAIRONET requests.
  
  SIOCGAIRONET allows userspace to query an(4) for various device
  properties and configuration, which appears to potentially include
  sensitive information such as WEP keys (an(4) seems to predate WPA).
  
  Also avoid races by copying in the request structure to a temporary
  buffer before locking and modifying the device softc.
  
  Reported by:  Ilja Van Sprundel <ivansprun...@ioactive.com>
  MFC after:    3 days
  Sponsored by: The FreeBSD Foundation

Modified:
  head/sys/dev/an/if_an.c

Modified: head/sys/dev/an/if_an.c
==============================================================================
--- head/sys/dev/an/if_an.c     Tue Dec 17 20:30:32 2019        (r355863)
+++ head/sys/dev/an/if_an.c     Tue Dec 17 21:34:38 2019        (r355864)
@@ -1875,6 +1875,7 @@ an_ioctl(struct ifnet *ifp, u_long command, caddr_t da
        int                     len;
        int                     i, max;
        struct an_softc         *sc;
+       struct an_req           *areq;
        struct ifreq            *ifr;
        struct thread           *td = curthread;
        struct ieee80211req     *ireq;
@@ -1934,17 +1935,21 @@ an_ioctl(struct ifnet *ifp, u_long command, caddr_t da
                error = 0;
                break;
        case SIOCGAIRONET:
-               error = copyin(ifr_data_get_ptr(ifr), &sc->areq,
-                   sizeof(sc->areq));
-               if (error != 0)
+               error = priv_check(td, PRIV_DRIVER);
+               if (error)
                        break;
+               areq = malloc(sizeof(*areq), M_TEMP, M_WAITOK);
+               error = copyin(ifr_data_get_ptr(ifr), areq, sizeof(*areq));
+               if (error != 0) {
+                       free(areq, M_TEMP);
+                       break;
+               }
                AN_LOCK(sc);
+               memcpy(&sc->areq, areq, sizeof(sc->areq));
 #ifdef ANCACHE
                if (sc->areq.an_type == AN_RID_ZERO_CACHE) {
-                       error = priv_check(td, PRIV_DRIVER);
-                       if (error)
-                               break;
                        sc->an_sigitems = sc->an_nextitem = 0;
+                       free(areq, M_TEMP);
                        break;
                } else if (sc->areq.an_type == AN_RID_READ_CACHE) {
                        char *pt = (char *)&sc->areq.an_val;
@@ -1960,12 +1965,14 @@ an_ioctl(struct ifnet *ifp, u_long command, caddr_t da
 #endif
                if (an_read_record(sc, (struct an_ltv_gen *)&sc->areq)) {
                        AN_UNLOCK(sc);
+                       free(areq, M_TEMP);
                        error = EINVAL;
                        break;
                }
+               memcpy(areq, &sc->areq, sizeof(*areq));
                AN_UNLOCK(sc);
-               error = copyout(&sc->areq, ifr_data_get_ptr(ifr),
-                   sizeof(sc->areq));
+               error = copyout(areq, ifr_data_get_ptr(ifr), sizeof(*areq));
+               free(areq, M_TEMP);
                break;
        case SIOCSAIRONET:
                if ((error = priv_check(td, PRIV_DRIVER)))
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to