possible bug in the sbappendrecord_locked()? (Was: Re: core dump
with bluetooth device)
Maksim Yevmenkin
maksim.yevmenkin at gmail.com
Fri Apr 17 02:22:16 UTC 2009
On Thu, Apr 16, 2009 at 5:39 PM, Maksim Yevmenkin
<maksim.yevmenkin at gmail.com> wrote:
> On Thu, Apr 16, 2009 at 12:59 PM, Alexander Best
> <alexbestms at math.uni-muenster.de> wrote:
>> hi there,
>>
>> i'm running r191076M. when i try to send files from my mobile phone to my
>> computer via bt the core dumps. here's a backtrace:
>>
>> Unread portion of the kernel message buffer:
>> sblastmbufchk: sb_mb 0xc8d54d00 sb_mbtail 0 last 0xc8d54d00
>> packet tree:
>> 0xc8d54d00
>> panic: sblastmbufchk from /usr/src/sys/kern/uipc_sockbuf.c:797
>> cpuid = 0
>
> are you, by change, have "options SOCKBUF_DEBUG" in your kernel?
ok, there is something strange going on in the
sbappendrecord_locked(). consider the following initial conditions:
1) sockbuf sb is empty, i.e. sb_mb == sb_mbtail == sb_lastrecord == NULL
2) sbappendrecord_locked() is given mbuf m0 with has exactly one mbuf,
i.e. m0->m_next == NULL
so
void
sbappendrecord_locked(struct sockbuf *sb, struct mbuf *m0)
{
struct mbuf *m;
SOCKBUF_LOCK_ASSERT(sb);
if (m0 == 0)
return;
m = sb->sb_mb;
if (m)
while (m->m_nextpkt)
m = m->m_nextpkt;
--> m is still NULL at this point
/*
* Put the first mbuf on the queue. Note this permits zero length
* records.
*/
sballoc(sb, m0);
SBLASTRECORDCHK(sb);
--> passed successfully, because sb_mb == sb_lastrecord == NULL (i.e.
sockbuf is empty)
SBLINKRECORD(sb, m0);
--> at this point sb_mb == sb_lastrecord == m0, _but_ sb_mtail == NULL
if (m)
m->m_nextpkt = m0;
else
sb->sb_mb = m0;
--> not sure about those lines above, didn't SBLINKRECORD(sb, m0) take
care of it already?
--> in any case, still, sb_mb == sb_lastrecord == m0 _and_ still
sb_mtail == NULL
m = m0->m_next;
m0->m_next = 0;
--> m is still NULL here
if (m && (m0->m_flags & M_EOR)) {
m0->m_flags &= ~M_EOR;
m->m_flags |= M_EOR;
}
--> sbcompress() is called with m == NULL, which is triggers the panic
(read below)
sbcompress(sb, m, m0);
}
===========
void
sbcompress(struct sockbuf *sb, struct mbuf *m, struct mbuf *n)
{
int eor = 0;
struct mbuf *o;
SOCKBUF_LOCK_ASSERT(sb);
while (m) {
--> lots of code that never gets executed because m == NULL
}
if (eor) {
KASSERT(n != NULL, ("sbcompress: eor && n == NULL"));
n->m_flags |= eor;
}
--> this where panic happens, because sb_mbtail is still NULL, but
sockbuf now contains exactly one record
SBLASTMBUFCHK(sb);
}
so, it looks like, sbcompress() should only be called when m != NULL.
also, when m == NULL, m0 should be marked as EOR.
comments anyone?
thanks,
max
More information about the freebsd-current
mailing list