[Bug 209545] Heap overflows in an driver

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Mon May 16 09:10:58 UTC 2016


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=209545

            Bug ID: 209545
           Summary: Heap overflows in an driver
           Product: Base System
           Version: 11.0-CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: freebsd-bugs at FreeBSD.org
          Reporter: cturt at hardenedbsd.org

The `an` driver doesn't perform bound checks on the lengths used by the
`AIROFLSHGCHR` and `AIROFLSHPCHR` commands implemented through
`SIOCGPRIVATE_0`, which leads to heap overflows from the `copyin` calls,
accessible by a privileged user only.

sys/dev/an/if_an.c:

static int
an_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
        ...

        switch (command) {
        ...
        case SIOCGPRIVATE_0:            /* used by Cisco client utility */
                if ((error = priv_check(td, PRIV_DRIVER)))
                        goto out;
                error = copyin(ifr->ifr_data, &l_ioctl, sizeof(l_ioctl));
                if (error)
                        goto out;
                mode = l_ioctl.command;

                AN_LOCK(sc);
                if (mode >= AIROGCAP && mode <= AIROGSTATSD32) {
                        error = readrids(ifp, &l_ioctl);
                } else if (mode >= AIROPCAP && mode <= AIROPLEAPUSR) {
                        error = writerids(ifp, &l_ioctl);
                } else if (mode >= AIROFLSHRST && mode <= AIRORESTART) {
                        error = flashcard(ifp, &l_ioctl);
                } else {
                        error =-1;
                }
                AN_UNLOCK(sc);
                if (!error) {
                        /* copy out the updated command info */
                        error = copyout(&l_ioctl, ifr->ifr_data,
sizeof(l_ioctl));
                }
                break;
        ...
out:

        return(error != 0);
}       

static int
flashcard(struct ifnet *ifp, struct aironet_ioctl *l_ioctl)
{
        int             z = 0, status;
        struct an_softc *sc;

        sc = ifp->if_softc;
        if (sc->mpi350) {
                if_printf(ifp, "flashing not supported on MPI 350 yet\n");
                return(-1);
        }
        status = l_ioctl->command;

        switch (l_ioctl->command) {
        ...
        case AIROFLSHGCHR:      /* Get char from aux */
                AN_UNLOCK(sc);
                status = copyin(l_ioctl->data, &sc->areq, l_ioctl->len);
                AN_LOCK(sc);
                if (status)
                        return status;
                z = *(int *)&sc->areq;
                if ((status = flashgchar(ifp, z, 8000)) == 1)
                        return 0;
                else
                        return -1;
        case AIROFLSHPCHR:      /* Send char to card. */
                AN_UNLOCK(sc);
                status = copyin(l_ioctl->data, &sc->areq, l_ioctl->len);
                AN_LOCK(sc);
                if (status)
                        return status;
                z = *(int *)&sc->areq;
                if ((status = flashpchar(ifp, z, 8000)) == -1)
                        return -EIO;
                else
                        return 0;
                break;
        ...

        return -EINVAL;
}

I propose that the following bound checks are added to this command:

        case AIROFLSHGCHR:      /* Get char from aux */
+               if (l_ioctl->len > sizeof(sc->areq)) {
+                       return -EINVAL;
+               }
...
        case AIROFLSHPCHR:      /* Send char to card. */
+               if (l_ioctl->len > sizeof(sc->areq)) {
+                       return -EINVAL;
+               }

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list