q: Memory modified after free in usb2
Hans Petter Selasky
hselasky at c2i.net
Thu Mar 26 00:59:36 PDT 2009
On Thursday 26 March 2009, Weongyo Jeong wrote:
> On Wed, Mar 25, 2009 at 10:46:54AM +0100, Hans Petter Selasky wrote:
> > > To solve this problem I modified codes slightly like below:
> > >
> > > usb2_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
> > > usb2_pause_mtx(NULL, 5 * hz);
> > > ...
> > > uath_free_rx_data_list(sc);
> > > uath_free_tx_data_list(sc);
> > > uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
> > >
> > > After adding it I couldn't see `Memory modified after free' messages
> > > anymore. My question is that I can't understand why adding
> > > usb2_pause_mtx() helps this symptom?
> >
> > Did you drain all the taskqueues before unsetup ?
>
> Yes. All I used was two callouts that the driver currently doesn't use
> usb2_proc_create() and tried to drain its before calling
> usb2_transfer_unsetup() but it still encounters `Memory modified after
> free'.
Hi,
Is this the link to the complete code?
http://perforce.freebsd.org/fileViewer.cgi?FSPC=//depot/user/weongyo/wireless/src/sys/dev/usb/wlan/if_uath.c&REV=24
1) The manpage states: "This function MUST NOT be called while holding any
locks ..."
| UATH_LOCK(sc);
| callout_drain(&sc->stat_ch);
| callout_drain(&sc->watchdog_ch);
505: 159831 21 | UATH_UNLOCK(sc);
callout_stop() is not callout_drain() !
Same sematics with USB2. transfer_stop()/transfer_drain()
2) Instead of copying the data twice, use the .ext_buffer=1 flag to instruct
USB to not allocate its own buffer in "struct usb2_config", see "umass.c" for
example, and the and
usb2_set_frame_data(xfer,
urb->transfer_buffer, 0);
Before you start the hardware!
Actually you can save alot of copying if you can exploit the multi-frame
feature of the USB-stack for BULK transfers! Then you have to set "frames >
1" in usb2_config structure. For example you would then copy in the header to
wMaxPacketSize bytes, and use the data pointer for the rest, given that the
IP-packet is not that defragged.
3) There is a chicken egg problem at detach.
I suspect that "uath_bulk_tx_callback()" is called with the USB_ERR_CANCELLED
error. And here you seem to access freed memory. I think you need to re-think
how you get that last node freed. Maybe it should be done by the if_stop()
and not at cancelled, because according to detach, you will do if_stop()
first and then cancel USB and unless you drain, you are not certain that the
callback is complete!
| default:
| data = STAILQ_FIRST(&sc->sc_datatx_active);
| if (data == NULL)
| goto setup;
2605: 159735 3 | if (data->ni != NULL) {
| ieee80211_free_node(data->ni);
| data->ni = NULL;
| ifp->if_oerrors++;
| }
2610: 159733 1 | if (xfer->error != USB_ERR_CANCELLED) {
| xfer->flags.stall_pipe = 1;
| goto setup;
| }
I recommend that you do the usb2_transfer_unsetup() first at detach like in
if_rum.c and the other WLAN drivers. That will solve your problem, and maybe
you have to fix the datatx_active queue, so that the last "data" is not stuck
there for ever ???
--HPS
More information about the freebsd-usb
mailing list