[Bug 206680] kbd race attacks

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Wed Jan 27 15:45:10 UTC 2016


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

            Bug ID: 206680
           Summary: kbd race attacks
           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

Whilst analysing my previous bug about the missing `splx` call in one of the
code paths for `genkbd_commonioctl`
(https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=206678), I decided to look
at the declaration for the macro itself, in `sys/sys/systm.h`:

/* Stubs for obsolete functions that used to be for interrupt management */
static __inline intrmask_t      splbio(void)            { return 0; }
static __inline intrmask_t      splcam(void)            { return 0; }
static __inline intrmask_t      splclock(void)          { return 0; }
static __inline intrmask_t      splhigh(void)           { return 0; }
static __inline intrmask_t      splimp(void)            { return 0; }
static __inline intrmask_t      splnet(void)            { return 0; }
static __inline intrmask_t      spltty(void)            { return 0; }
static __inline void            splx(intrmask_t ipl __unused)   { return; }

Since these functions have been removed, but kbd has not been updated to
account for this, it means that none of the kbd code is thread safe.

For example, `kbd_realloc_array` contains a lovely, possible race attack:

        s = spltty();
        newsize = ((keyboards + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
        new_kbd = malloc(sizeof(*new_kbd)*newsize, M_DEVBUF, M_NOWAIT|M_ZERO);
        if (new_kbd == NULL) {
                splx(s);
                return (ENOMEM);
        }
        new_kbdsw = malloc(sizeof(*new_kbdsw)*newsize, M_DEVBUF,
                            M_NOWAIT|M_ZERO);
        if (new_kbdsw == NULL) {
                free(new_kbd, M_DEVBUF);
                splx(s);
                return (ENOMEM);
        }
        bcopy(keyboard, new_kbd, sizeof(*keyboard)*keyboards);
        bcopy(kbdsw, new_kbdsw, sizeof(*kbdsw)*keyboards);
        if (keyboards > 1) {
                free(keyboard, M_DEVBUF);
                free(kbdsw, M_DEVBUF);
        }
        keyboard = new_kbd;
        kbdsw = new_kbdsw;
        keyboards = newsize;
        splx(s);

This code would have been safe because of the `spltty`, and `splx` locks, but
since these functions no longer do anything, we have a very brief window where
the buffers have been freed, but have not been set to the new allocations. If
the thread were to be preempted at this point, and another thread attempted to
use the buffers, a use after free would occur.

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


More information about the freebsd-bugs mailing list