kern/99779: kernel panic due to Invlalid next packet
identification in soreceive()
JINMEI Tatuya / 神明達哉
jinmei at isl.rdc.toshiba.co.jp
Thu Jul 6 05:00:36 UTC 2006
The following reply was made to PR kern/99779; it has been noted by GNATS.
From: JINMEI Tatuya / =?ISO-2022-JP?B?GyRCP0BMQEMjOkgbKEI=?= <jinmei at isl.rdc.toshiba.co.jp>
To: Maxim Konovalov <maxim at macomnet.ru>
Cc: bug-followup at freebsd.org
Subject: Re: kern/99779: kernel panic due to Invlalid next packet identification in soreceive()
Date: Thu, 06 Jul 2006 13:57:55 +0900
>>>>> On Tue, 4 Jul 2006 17:03:30 +0400 (MSD),
>>>>> Maxim Konovalov <maxim at macomnet.ru> said:
> Could you please update your system to RELENG_6 branch and check if
> this fix the problem you describe? gnn@ MFC'ed a similar fix there as
> part of kern/83885 work a couple of weeks ago (uipc_socket.c
> rev. 1.243 in HEAD and rev. 1.242.2.5 in RELENG_6).
Thanks for the prompt response. I've not noticed the rev-1.243 fix (I
should have checked the repository history more closely...), but in
any event I don't think the change in that revision is really correct.
(I've not upgraded the entire kernel to RELENG_6, but applied the patch
introduced in rev. 1.243 and confirmed the problem described below).
In fact, it does not catch the case where the socket buffer has two
"packets": one that only consists of control mbufs and the other that
follows the control-only packet. In this case, m = NULL, but
so->so_rcv.sb_mb is not because sockbuf_pushsync() after the do-while
loop sets sb_mb to the original 'nextrecord'. Then the RELENG_6 code
sets nextrecord to NULL (sb_mb->m_nextpkt) at this point:
if (so->so_rcv.sb_mb != NULL)
nextrecord = so->so_rcv.sb_mb->m_nextpkt;
while nextrecord should actually be so->so_rcv.sb_mb.
This discrepancy subsequently causes socket buffer inconsistency at
the following point of the code:
/*
* First part is an inline SB_EMPTY_FIXUP(). Second
* part makes sure sb_lastrecord is up-to-date if
* there is still data in the socket buffer.
*/
so->so_rcv.sb_mb = nextrecord;
if (so->so_rcv.sb_mb == NULL) {
so->so_rcv.sb_mbtail = NULL;
so->so_rcv.sb_lastrecord = NULL;
} else if (nextrecord->m_nextpkt == NULL)
that is, sb_mb is set to NULL even though there is an unreceived
packet in the socket. This will eventually cause a kernel panic.
Using the problem description in kern/83885, this bug can be revealed
by "ping6 -m -s 1300 -v PC2" (i.e., adding -v). Then the ICMPv6 Too
Big message follows the control mbuf and reproduced the situation
described above.
On the other hand, my patch correctly fixes both the problems.
More information about the freebsd-bugs
mailing list