Subject: Re: kern/22002: panic: double tcp_freeq() may happen - TAILQ_*
To: Havard Eidnes <he@nordu.net>
From: enami tsugutomo <enami@but-b.or.jp>
List: netbsd-bugs
Date: 06/28/2003 07:38:38
> However, contrary to what tcp_freeq()
> expect, it appears that the segq and timeq queues are of different
> length:

Depending on where the pool_do_put + 0x35e is, the page which this tp
was allocated from may be allready back to system and reuse for
another use.  Is the rest of *tp looks valid?

> (gdb) up 10
> #10 0xc01bf150 in tcp_freeq (tp=0xc089f164)
>     at /sys/arch/i386/compile/BLACKHOLE/../../../../netinet/tcp_subr.c:1181
> 1181                    TAILQ_REMOVE(&tp->segq, qe, ipqe_q);
> (gdb) p tp
> $1 = (struct tcpcb *) 0xc089f164
> (gdb) p tp->segq
> $2 = {tqh_first = 0xc0867b04, tqh_last = 0xc089f168}

tp->segq is already inconsitient, since tqh_last points
&tp->segq.tqh_first and this means this tailq is empty but tqh_first
disagrees.

> (gdb) p tp->timeq
> $6 = {tqh_first = 0x0, tqh_last = 0xc089f294}

This tqh_last should be &tp->timeq.tqh_first, but is it so?  For usual
sizeof(struct tcpcb), the value is beyond the struct.

> Hm,
> 
> > >Fix:
> > 	Explicitly mark queues as empty when they have been released
> > 	in tcp_freeq()?

Mark inp_ppcb NULL a bit earlier so that tcp_drain won't pick up this?

enami.