Subject: kern/5542: lfs_markv potential buffer overrun
To: None <gnats-bugs@gnats.netbsd.org>
From: None <perseant@hhhh.org>
List: netbsd-bugs
Date: 06/04/1998 21:20:51
>Number: 5542
>Category: kern
>Synopsis: lfs_markv can miscalculate bytes left in segsum, overflowing it
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Jun 4 21:20:00 1998
>Last-Modified:
>Originator: Konrad Schroder
>Organization:
Konrad Schroder http://www.hitl.washington.edu/people/perseant/
System Administrator perseant@hitl.washington.edu
Human Interface Technology Lab Voice: (206) 616-1478
Box 352142, University of Washington, 98195, USA FAX: (206) 543-5380
>Release: 3 Jun 1998, plus patches for all recent open LFS PRs (4641, 4965, 5013, 5121).
>Environment:
System: NetBSD inle 1.3 NetBSD 1.3 (INLE) #1: Sun Apr 19 15:01:29 PDT 1998 perseant@gro:/usr/src/sys/arch/i386/compile/INLE i386
>Description:
lfs_markv assumes through its main loop that the FINFO structure into
which it is writing is accounted for in sum_bytes_left. However, it
can call lfs_writeseg (through lfs_fastvget, lfs_vcreate, getnewvnode,
lfs_vflush), which returns with "zero" FINFOs accounted for...which
means that the byte accounting for the segment summary is short by
sizeof(FINFO) - sizeof(ufs_daddr_t). This undercounting later causes
an overfilling of the segsum block, overwriting random kernel memory
and causing unpredictable panics, in and out of LFS code.
>How-To-Repeat:
Build an LFS kernel with DEBUG and DIAGNOSTIC (MALLOCLOG will be helpful
as well), make an LFS, and use it until cleaning occurs. Several errors
may be seen (some caused by this problem, others not...this is not the
"last bug", in particular I believe that there is another miscalc/overflow
somewhere in the code). Note that for some reason, I've only been able to
get this bug to manifest itself on i386, and not, say, sparc.
>Fix:
Here is a patch that I believe should take care of the problem (unless
lfs_fastvget fails, then you have to add the same lines just above):
*** lfs_syscalls.c Thu Apr 9 19:01:31 1998
--- lfs_syscalls.c.new Thu Jun 4 20:55:02 1998
***************
*** 192,195 ****
--- 192,203 ----
continue;
}
+ if(((SEGSUM *)(sp->segsum))->ss_nfinfo == 0) {
+ sp->sum_bytes_left -= sizeof(FINFO) - sizeof(ufs_daddr_t);
+ INC_FINFO(sp);
+ sp->start_lbp = &sp->fip->fi_blocks[0];
+ sp->fip->fi_version = blkp->bi_version;
+ sp->fip->fi_nblocks = 0;
+ sp->fip->fi_ino = blkp->bi_inode;
+ }
sp->vp = vp;
ip = VTOI(vp);
>Audit-Trail:
>Unformatted: