On Wed, Dec 13, 2000 at 09:59:06PM +0000, Dag Brattli wrote:
> Hi,
> 
> To me it sounds like somebody have sent a frame down the IrDA stack, that
> is still one somebodies list, or somebody is some how touching the skb next pointer
> after it's been passed down the stack. The frame has been queued by IrLAP waiting
> for ack, but somebody is changing the list pointer (next) while it's sitting in this 
>queue.
> So when an incomming frame acks this frame, and IrLAP tries to dequeue it, then
> it will try to follow that NULL pointer.
> 
> Are you sure nobody changes the skb after it's been passed down the stack? Maybe
> it's sitting on somebodies list further up, or somebody clears it's struct or 
>something!?
> 
> -- Dag

        Good point ! Unfortunately, we will have to find another thing
to blame.

        If you look carefully at the code in skbuff.h/skbuff.c and co,
the only way to have next == NULL is if someone free, dequeue or
unlink the skb. I can't see any other operation setting this stuff to
NULL.
        As skb_dequeue(), skb_dequeue_tail() explicitely check that
the skb is in the relevant list, and kfree_skb() check explicitely
that it is not in a list (log message in that case), we must assume
that it would happen through an skb_unlink().

        Both IrDA and ppp doesn't use skb_unlink() :-(
        We could still assume kfree_skb() and assume that the relevant
log messages were cut out of the report. Hum...


        Now, a little analisys of IrNET :
        Packets are sent to IrNET by ppp_generic.c. There are two
places doing that, and they look like :
------------------------------
                        skb = skb_dequeue(&pch->file.xq);
                        if (!pch->chan->ops->start_xmit(pch->chan, skb)) {
                                /* put the packet back and try again later */
                                skb_queue_head(&pch->file.xq, skb);
                                break;
                        }
------------------------------
        And
------------------------------
        while (ppp->xmit_pending == 0
               && (skb = skb_dequeue(&ppp->file.xq)) != 0)
                ppp_send_frame(ppp, skb);
[...]
        ppp->xmit_pending = skb;
        ppp_push(ppp);
[...]
        struct sk_buff *skb = ppp->xmit_pending;
[...]
                        if (pch->chan->ops->start_xmit(pch->chan, skb))
                                ppp->xmit_pending = 0;
------------------------------
        They both use skb_dequeue() and seem proper...

        And in IrNET, we have :
---------------------
  /* Is the skb headroom large enough to contain all IrDA-headers? */
  if((skb_headroom(skb) < (ap->max_header_size + needaddr)) ||
      (skb_shared(skb)))
    {
      struct sk_buff *  new_skb;

      DEBUG(PPP_INFO, "Reallocating skb\n");
---------------------
        So, if the skb is shared, we don't pass it to IrDA.

        One sure way to tell if the skb is still in a list when
comming to IrNET would be to force reallocation above and see if kfree
complains about it.

        Anyway, I think I should be able to see this bug it in my
testing ?

        Jean
_______________________________________________
Linux-IrDA mailing list  -  [EMAIL PROTECTED]
http://www.pasta.cs.UiT.No/mailman/listinfo/linux-irda

Reply via email to