On Thu, Apr 02, 2020 at 12:51:45PM BST, Stefan Sperling wrote:
> On Thu, Apr 02, 2020 at 12:40:46PM +0100, Raf Czlonka wrote:
> > On Thu, Apr 02, 2020 at 12:30:15PM BST, Stefan Sperling wrote:
> > > On Thu, Apr 02, 2020 at 11:43:34AM +0100, Raf Czlonka wrote:
> > > > I've just tested it but, whilst I don't get a panic when I *un*plug
> > > > the USB NIC, I *do* get the same panic when I *plug* it back in :^(
> > >
> > > Insufficient detail. Please show the panic.
> > >
> > > We need to know what you are actually seeing, not your interpretation of
> > > what you are seeing. Even if your interpretation happens to be correct,
> > > letting us see the same data allows for independent verification.
> >
> > Hi Stefan,
> >
> > Sure, better be thorough so here it is:
> >
> > panic: Data modified on freelist: word 10 of object 0xffff80000099a000
> > size 0x2000 previous type devbuf (0xdead410f != 0xdead4110)
> >
> > I hadn't copy-pasted it - I typed it in form a photo taken this morning.
>
> Thank you.
>
> My suspicion is that ic->ic_bss gets freed in ieee80211_ifdetach(), and
> afterwards ic->ic_bss->ni_refcnt gets decremented in zyd_free_tx_list().
> Note that (0xdead4110 - 1) == 0xdead410f.
>
> If my theory is correct then when the bug occurs the values of
> ic->ic_bss->ni_refcnt are:
>
> before ieee80211_ifdetach(): ic->ic_bss->ni_refcnt == 1
> after ieee80211_ifdetach(): ic->ic_bss->ni_refcnt == 0xdead4110
> after zyd_free_tx_list(): ic->ic_bss->ni_refcnt == 0xdead410f
>
> Can you please try the following diff?
> In addition to the previous diff which fixes a potential use-after-free
> when an error happens during Tx of a frame, this changes the order of
> operations during detach such that the result should be:
>
> before zyd_free_tx_list(): ic->ic_bss->ni_refcnt == 1
> after zyd_free_tx_list(): ic->ic_bss->ni_refcnt == 0
> after ieee80211_ifdetach(): ic->ic_bss->ni_refcnt == 0xdead4110
>
> No panic expected since malloc will see the expected pattern written by free.
Hi Stefan,
After I got it to timeout, I ran /etc/netstart and unplugged it,
then plugged it again - no panic. I had to poke it a bit to get it
working again but, even when it was up and I unplugged it then,
still no panic.
Thanks a lot for your help! :^)
Now, is there anything that can be done regarding the timeouts?
Cheers,
Raf
zyd0: HMAC ZD1211, FW 46.05, RF RFMD, PA 0, address [...]
splassert: ieee80211_free_node: want 7 have 4
zyd0: device timeout
zyd0: could not transmit buffer: TIMEOUT
zyd0: device timeout
zyd0: could not transmit buffer: TIMEOUT
splassert: ieee80211_free_node: want 7 have 4
zyd0 detached
zyd0 at uhub0 port 2 configuration 1 interface 0 "3COM 3CRUSB10075" rev
2.00/43.30 addr 2
zyd0: HMAC ZD1211, FW 46.05, RF RFMD, PA 0, address [...]
splassert: ieee80211_free_node: want 7 have 4
zyd0 detached
zyd0 at uhub0 port 2 configuration 1 interface 0 "3COM 3CRUSB10075" rev
2.00/43.30 addr 2
zyd0: HMAC ZD1211, FW 46.05, RF RFMD, PA 0, address [...]
splassert: ieee80211_free_node: want 7 have 4
> diff 9d8a60ff1dae84d5c890bdc5040be018a3bdd3dc /usr/src
> blob - 61dc357bf69a56d1ce282d505eecd343b0eb2465
> file + sys/dev/usb/if_zyd.c
> --- sys/dev/usb/if_zyd.c
> +++ sys/dev/usb/if_zyd.c
> @@ -434,14 +434,14 @@ zyd_detach(struct device *self, int flags)
> return 0;
> }
>
> + zyd_free_rx_list(sc);
> + zyd_free_tx_list(sc);
> +
> if (ifp->if_softc != NULL) {
> ieee80211_ifdetach(ifp);
> if_detach(ifp);
> }
>
> - zyd_free_rx_list(sc);
> - zyd_free_tx_list(sc);
> -
> sc->attached = 0;
>
> splx(s);
> @@ -2216,6 +2216,7 @@ zyd_tx(struct zyd_softc *sc, struct mbuf *m, struct ie
> ZYD_TX_TIMEOUT, zyd_txeof);
> error = usbd_transfer(data->xfer);
> if (error != USBD_IN_PROGRESS && error != 0) {
> + data->ni = NULL;
> ifp->if_oerrors++;
> return EIO;
> }