Subject: kern/5542: lfs_markv potential buffer overrun
To: None <>
From: None <>
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
>Originator:     Konrad Schroder
Konrad Schroder 
System Administrator               
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).
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
    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.
    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.
    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
---  Thu Jun  4 20:55:02 1998
*** 192,195 ****
--- 192,203 ----
+                         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);