Subject: bin/36078: pstat segfaults when used for kernel core file with -v and -T options
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <antiright@gmail.com>
List: netbsd-bugs
Date: 03/24/2007 11:20:01
>Number: 36078
>Category: bin
>Synopsis: pstat segfaults when used for kernel core file with -v and -T options
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Mar 24 11:20:00 +0000 2007
>Originator: Jeffrey Bedard
>Release: 4.99.16 (amd64)
>Organization:
>Environment:
NetBSD antiright.dyndns.org 4.99.16 NetBSD 4.99.16 (AR) #7: Thu Mar 22 08:41:32 EDT 2007 root@antiright.dyndns.org:/usr/sources/src-current/sys/arch/amd64/compile/AR amd64
>Description:
pstat segfaults when used on a kernel core file when the -T or -v options are specified. This segfault occurs in kinfo_vnodes(), according to gdb.
(gdb) r -M netbsd.0.core -T
Starting program: /usr/sbin/pstat -M netbsd.0.core -T
...
230/3404 files
Program received signal SIGSEGV, Segmentation fault.
0x000000000040240b in kinfo_vnodes ()
(gdb) r -M netbsd.0.core -v
...
Starting program: /usr/sbin/pstat -M netbsd.0.core -v
...
Program received signal SIGSEGV, Segmentation fault.
0x000000000040240b in kinfo_vnodes ()
(gdb) bt
#0 0x000000000040240b in kinfo_vnodes ()
#1 0x00000000004024ba in loadvnodes ()
#2 0x0000000000402688 in vnodemode ()
#3 0x0000000000402f7a in main ()
Running with pstat compiled with -g3:
0x0000000000402e99 in kinfo_vnodes (avnodes=0x7f7fffffdfbc) at pstat.c:744
744 TAILQ_FOREACH(vp, &mount.mnt_vnodelist, v_mntvnodes) {
>How-To-Repeat:
pstat -M netbsd.0.core -v
pstat -M netbsd.0.core -T
>Fix:
vp->v_mntvnodes.tqe_next within TAILQ_FOREACH is the source of the segfault. vp is uninitialized before this call.
patch:
--- pstat.c.orig 2007-03-24 06:14:47.000000000 -0400
+++ pstat.c 2007-03-24 07:12:33.000000000 -0400
@@ -731,25 +731,30 @@
struct vnode *vp, vnode;
char *beg, *bp, *ep;
int numvnodes;
-
+
KGET(V_NUMV, numvnodes);
if ((bp = malloc((numvnodes + 20) * (VPTRSZ + VNODESZ))) == NULL)
err(1, "malloc");
beg = bp;
ep = bp + (numvnodes + 20) * (VPTRSZ + VNODESZ);
KGET(V_MOUNTLIST, mountlist);
+
+ vp=(struct vnode *)bp;
+
for (mp = mountlist.cqh_first;;
mp = mount.mnt_list.cqe_next) {
KGET2(mp, &mount, sizeof(mount), "mount entry");
- TAILQ_FOREACH(vp, &mount.mnt_vnodelist, v_mntvnodes) {
- KGET2(vp, &vnode, sizeof(vnode), "vnode");
- if (bp + VPTRSZ + VNODESZ > ep)
+ if(vp->v_mntvnodes.tqe_next != NULL) {
+ TAILQ_FOREACH(vp, &mount.mnt_vnodelist, v_mntvnodes) {
+ KGET2(vp, &vnode, sizeof(vnode), "vnode");
+ if (bp + VPTRSZ + VNODESZ > ep)
/* XXX - should realloc */
- errx(1, "no more room for vnodes");
- memmove(bp, &vp, VPTRSZ);
- bp += VPTRSZ;
- memmove(bp, &vnode, VNODESZ);
- bp += VNODESZ;
+ errx(1, "no more room for vnodes");
+ memmove(bp, &vp, VPTRSZ);
+ bp += VPTRSZ;
+ memmove(bp, &vnode, VNODESZ);
+ bp += VNODESZ;
+ }
}
if (mp == mountlist.cqh_last)
break;