Hello Thomas,

Thanks for this bug report.

On 09/04/15(Thu) 13:11, Thomas Pfaff wrote:
> Hi.
> 
> I disconnected an "arduino" device (this particular one is a cheap
> chinese knock-off) while being connected to its serial port and ...
> 
>    $ cu -l cuaU0
>    Connected to /dev/cuaU0 (speed 9600)
>    ucom0 detached
>    uchcom0 detached
> 
>    [EOT]
>    kernel: protection fault trap, code=0
>    Stopped at      ehci_check_intr+0x12:   movzbl  0x3(%rax),%eax
>    ddb{0}> 
> 
> This device attaches to uchcom(4) while the other (genuine) ones
> that I have attach to umodem(4) and does not cause this problem.
> 
>    $ cu -l cuaU0
>    Connected to /dev/cuaU0 (speed 9600)
>    ucom0 detached
>    umodem0 detached
> 
>    [EOT]
>    $
> 
> Transcript and some pictures (of ps and show reg) follows.
> 
> $ cu -l cuaU0
> Connected to /dev/cuaU0 (speed 9600)
> ucom0 detached
> uchcom0 detached
> 
> [EOT]
> kernel: protection fault trap, code=0
> Stopped at      ehci_check_intr+0x12:   movzbl  0x3(%rax),%eax
> ddb{0}> trace
> ehci_check_intr() at ehci_check_intr+0x12
> ehci_softintr() at ehci_softintr+0x3f
> softintr_dispatch() at softintr_dispatch+0x7f
> Xsoftnet() at Xsoftnet+0x2d

It seems that uchcom(4) has a bug preventing it's interrupt pipe from
being close.  This has the side effect of leaking a xfer and triggering
the NULL-dereference you're seeing if an interrupt occurs after the
pipe has been freed.

Could you test the diff below and tell me if it fixes this issue?

Index: uchcom.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uchcom.c,v
retrieving revision 1.23
diff -u -p -r1.23 uchcom.c
--- uchcom.c    14 Mar 2015 03:38:49 -0000      1.23
+++ uchcom.c    13 Apr 2015 09:00:04 -0000
@@ -814,9 +814,6 @@ uchcom_close_intr_pipe(struct uchcom_sof
 {
        usbd_status err;
 
-       if (usbd_is_dying(sc->sc_udev))
-               return;
-
        if (sc->sc_intr_pipe != NULL) {
                usbd_abort_pipe(sc->sc_intr_pipe);
                err = usbd_close_pipe(sc->sc_intr_pipe);
@@ -911,9 +908,6 @@ void
 uchcom_close(void *arg, int portno)
 {
        struct uchcom_softc *sc = arg;
-
-       if (usbd_is_dying(sc->sc_udev))
-               return;
 
        uchcom_close_intr_pipe(sc);
 }

Reply via email to