tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Bug in uhidev, and possible solution



After more testing, it seems that checking if the status is
USBD_INVAL is not really reliable - in fact there is a possibility of a crash.

Replacing the code to check if status is USBD_INVAL with this:

if(sc->sc_ipipe == NULL && sc->sc_opipe == NULL
        && sc->sc_oxfer == NULL)
        return;
        
fixes the issue.

This code is safer (after all it checks for the values set by the
error handling code),
but there is possibly a cleaner way of doing it; unfortunately I do
not know the internals
of usbhid or how USB support is implemented in NetBSD beyond what I
needed to understand
in order to come with the solution to my issue.

In any case, I'm attaching a patch again, hopefully this is the last time :)


On 12/26/13, Just a Normal Person <tails92%gmail.com@localhost> wrote:
> My machine would crash once I exited any SDL application; I researched the
> issue
> and the uhidev code was the culprit.
>
> The crash happened after the free() call in the following part of
> uhidev_close(),
> in sys/dev/usb/uhidev.c:
>
> vvvvvvv
>
> if (sc->sc_ibuf != NULL) {
>       free(sc->sc_ibuf, M_USBDEV); // <-- this is the call
>       sc->sc_ibuf = NULL;
> }
>
> ^^^^^^^
>
> Now the reason for which this bug happens is because the libSDL code
> triggers
> a call to uhidev_open(), which fails.
> There would be no problem here, but in the error handling code
> after freeing the memory area pointed by sc->sc_ibuf, sc->sc_ibuf is
> not set to NULL;
> this makes free() try to free the memory pointed by sc->sc_ibuf again,
> which
> obviously leads to an error where free() gets wrong addresses for the
> start and end VM addresses,
> leading to the following assertion being fired at line 521 of
> uvm_km.c, in uvm_km_pgremove_intrsafe():
>
> KASSERT(start < end);
>
> To fix the issue, my proposed solution is:
>
> - setting sc->sc_ibuf to NULL in the error handling code in
> uhidev_open() after freeing the memory
>   pointed by it
> - checking if the status is USBD_INVAL in uhidev_intr() at the very
> beginning, right after
>   the variable declarations; if the status is USBD_INVAL the function
> does nothing.
>   This is necessary otherwise the code in uhidev_intr() would be using
> the content of sc->sc_ibuf, now
>   set to NULL after the error in uhidev_open(), causing a trap.
>
> I am running NetBSD amd64; the sources of the kernel I used is the
> December 24th snapshot of HEAD
> from nyftp.netbsd.org - should not be a problem considering the
> changes are small, and that
> sys/dev/usb/uhidev.c has not received an update since October.
> I enabled both the DIAGNOSTIC and DEBUG options in the kernel
> configuration.
>
> By the way, I am attaching a patch which can be used to patch
> sys/dev/usb/uhidev.c in the way
> I described.
>

Attachment: uhidev.c.patch
Description: Binary data



Home | Main Index | Thread Index | Old Index