Subject: kern/34674: Panic in tcp_input() by integer division fault
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Christian Biere <christianbiere@gmx.de>
List: netbsd-bugs
Date: 09/30/2006 14:50:00
>Number: 34674
>Category: kern
>Synopsis: Panic in tcp_input() by integer division fault
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Sep 30 14:50:00 +0000 2006
>Originator: Christian Biere
>Release: NetBSD 4.99.3
>Environment:
System: NetBSD cyclonus 4.99.3 NetBSD 4.99.3 (STARSCREAM) #2: Sat Sep 30 16:12:53 CEST 2006 src@cyclonus:/o/NetBSD/obj/sys/arch/i386/compile/STARSCREAM i386
Architecture: i386
Machine: i386
>Description:
NetBSD as of today crashes instantly with a "integer division fault" in tcp_input()
when I start gtk-gnutella. This bug must have been added within the last few days
(up to a week maybe). The first patch shows the place at I suspect the divison-by-zero
occurs. savecore is currently broken for me, so I had to look at the assemble code
at "eip" with gdb.
Adding a check against zero helped against this panic but lead to another
in m_copydata() due to a negative length of "-12".
I reverted the last modification to tcp_output.c and this seems to have fixed
the latter panic. I presume this last change introduced an underflow or off-by-one
bug.
>How-To-Repeat:
Any TCP-heavy application with many connections should trigger this panic.
>Fix:
Index: tcp_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_input.c,v
retrieving revision 1.244
diff -u -p -u -r1.244 tcp_input.c
--- tcp_input.c 5 Sep 2006 00:29:36 -0000 1.244
+++ tcp_input.c 30 Sep 2006 13:37:28 -0000
@@ -2386,7 +2386,7 @@ after_listen:
* NewReno and we have only received partial acks), do not
* inflate the window yet.
*/
- if (tp->t_partialacks < 0) {
+ if (tp->t_partialacks < 0 && tp->snd_cwnd > 0) {
u_int cw = tp->snd_cwnd;
u_int incr = tp->t_segsz;
Index: tcp_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_output.c,v
retrieving revision 1.144
retrieving revision 1.143
diff -u -r1.144 -r1.143
--- tcp_output.c 28 Sep 2006 04:32:47 -0000 1.144
+++ tcp_output.c 5 Sep 2006 00:29:36 -0000 1.143
@@ -1,4 +1,4 @@
-/* $NetBSD: tcp_output.c,v 1.144 2006/09/28 04:32:47 dbj Exp $ */
+/* $NetBSD: tcp_output.c,v 1.143 2006/09/05 00:29:36 rpaulo Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -142,7 +142,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.144 2006/09/28 04:32:47 dbj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.143 2006/09/05 00:29:36 rpaulo Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@@ -397,8 +397,7 @@
* transmit.
*/
if (so)
- *txsegsizep = min((so->so_snd.sb_hiwat -
- so->so_snd.sb_lowat + 1) >> 1, *txsegsizep);
+ *txsegsizep = min(so->so_snd.sb_hiwat >> 1, *txsegsizep);
*rxsegsizep = min(tp->t_ourmss - optlen, size);
if (*txsegsizep != tp->t_segsz) {