misc/112126: netstat segfaults on unusual ICMP statistics
Christoph Weber-Fahr
cwf-ml at arcor.de
Wed Apr 25 15:40:10 UTC 2007
>Number: 112126
>Category: misc
>Synopsis: netstat segfaults on unusual ICMP statistics
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Apr 25 15:40:09 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator: Christoph Weber-Fahr
>Release: 6.1-RELEASE-p15
>Organization:
Arcor AG
>Environment:
FreeBSD xxxxx.arcor.net 6.1-RELEASE-p15 FreeBSD 6.1-RELEASE-p15 #0: Thu Apr 19 02:40:15 CEST 2007 root at xxxxx.arcor.net:/usr/obj/usr/src/sys/DL380 i386
>Description:
we have a number of very busy publicly available production servers running FreeBSD.
On some of these systems, netstat -s fails with a segmentation fault. This is especially problematic, since system monitoring tools use netstat periodically to gather statistics.
I looked into the issue in the netstats sources. The netstat utility mainatins an internal array for ICMP type names. But for listing the icmp statistics it relies on the ICMP_MAXTYPE kernel define pulled from the syestem include files.
Those values are badly out of sync - ICMP_MAXTYPE is at 40, while netstat's name array has just 19 entries. So, as soon as the kernel has logged a stat for an icmp type > 19, netstat -s dumps core.
>How-To-Repeat:
send some ICMP packets with ICMP type > 19 to the machine
run netstat -s
>Fix:
the appended patch
- enhances netstat's array to 40 with names from the include file
- provides a mechanism to deal gracefully with such a situation
schould it arise in the future again.
The patch was created and tested on FreeBSD 6.1-p15. It was also tested on FreeBSD 6.2-p3.
Patch attached with submission follows:
--- usr.bin/netstat/inet.c.org Wed Apr 25 15:44:51 2007
+++ usr.bin/netstat/inet.c Wed Apr 25 17:19:17 2007
@@ -653,8 +653,32 @@
"information request reply",
"address mask request",
"address mask reply",
+ "#19",
+ "#20",
+ "#21",
+ "#22",
+ "#23",
+ "#24",
+ "#25",
+ "#26",
+ "#27",
+ "#28",
+ "#29",
+ "icmp traceroute",
+ "data conversion error",
+ "mobile host redirect",
+ "IPv6 where-are-you",
+ "IPv6 i-am-here",
+ "mobile registration req",
+ "mobile registration reply",
+ "#37",
+ "#38",
+ "icmp SKIP",
+ "icmp photuris",
};
+static const int max_known_icmpname=40;
+
/*
* Dump ICMP statistics.
*/
@@ -698,8 +722,13 @@
printf("\tOutput histogram:\n");
first = 0;
}
- printf("\t\t%s: %lu\n", icmpnames[i],
- icmpstat.icps_outhist[i]);
+ if (i <= max_known_icmpname) {
+ printf("\t\t%s: %lu\n", icmpnames[i],
+ icmpstat.icps_outhist[i]);
+ } else {
+ printf("\t\tunknown ICMP #%d: %lu\n", i,
+ icmpstat.icps_outhist[i]);
+ }
}
p(icps_badcode, "\t%lu message%s with bad code fields\n");
p(icps_tooshort, "\t%lu message%s < minimum length\n");
@@ -713,8 +742,13 @@
printf("\tInput histogram:\n");
first = 0;
}
- printf("\t\t%s: %lu\n", icmpnames[i],
- icmpstat.icps_inhist[i]);
+ if (i <= max_known_icmpname) {
+ printf("\t\t%s: %lu\n", icmpnames[i],
+ icmpstat.icps_inhist[i]);
+ } else {
+ printf("\t\tunknown ICMP #%d: %lu\n", i,
+ icmpstat.icps_inhist[i]);
+ }
}
p(icps_reflect, "\t%lu message response%s generated\n");
p2(icps_badaddr, "\t%lu invalid return address%s\n");
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list