From kato@eclogite.eps.nagoya-u.ac.jp  Tue Mar  4 11:02:06 1997
Received: from gneiss.eps.nagoya-u.ac.jp (gneiss.eps.nagoya-u.ac.jp [133.6.57.99])
          by freefall.freebsd.org (8.8.5/8.8.5) with ESMTP id LAA08107
          for <FreeBSD-gnats-submit@freebsd.org>; Tue, 4 Mar 1997 11:01:59 -0800 (PST)
Received: (from kato@localhost) by gneiss.eps.nagoya-u.ac.jp (8.8.5/3.4W4) id EAA01847; Wed, 5 Mar 1997 04:01:49 +0900 (JST)
Message-Id: <199703041901.EAA01847@gneiss.eps.nagoya-u.ac.jp>
Date: Wed, 5 Mar 1997 04:01:49 +0900 (JST)
From: kato@eclogite.eps.nagoya-u.ac.jp
Reply-To: kato@eclogite.eps.nagoya-u.ac.jp
To: FreeBSD-gnats-submit@freebsd.org
Subject: vinvalbuf() clobbers b_vnbufs chain
X-Send-Pr-Version: 3.2

>Number:         2875
>Category:       kern
>Synopsis:       vinvalbuf() may clobber b_vnbufs chain.
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Mar  4 11:10:01 PST 1997
>Closed-Date:    Tue Mar 4 21:03:15 PST 1997
>Last-Modified:  Tue Mar  4 21:05:09 PST 1997
>Originator:     KATO Takenori
>Release:        FreeBSD 2.2-GAMMA i386
>Organization:
Dept. Earth Planet. Sci, Nagoya Univ, Japan
>Environment:



>Description:


The function vinvalbuf() in vfs_subr.c may clober b_vnbufs chain.

in vinvalbuf():

	s = splbio();
	for (;;) {
		...
		for (bp = blist; bp; bp = nbp) {
			...
			if (bp->b_flags & B_BUSY) {
				...
				splx(s);	<--- (1)
				...
				break;		<--- (2)
			}
		}
	}

Because disk I/O interruption is unmasked at (1), b_vnbufs is operated 
without splbio() after `break' at (2).

>How-To-Repeat:

	

>Fix:
	

*** vfs_subr.c.orig	Wed Mar  5 03:03:56 1997
--- vfs_subr.c	Wed Mar  5 03:44:00 1997
***************
*** 481,488 ****
  			panic("vinvalbuf: dirty bufs");
  	}
  
- 	s = splbio();
  	for (;;) {
  		if ((blist = vp->v_cleanblkhd.lh_first) && (flags & V_SAVEMETA))
  			while (blist && blist->b_lblkno < 0)
  				blist = blist->b_vnbufs.le_next;
--- 481,488 ----
  			panic("vinvalbuf: dirty bufs");
  	}
  
  	for (;;) {
+ 		s = splbio();
  		if ((blist = vp->v_cleanblkhd.lh_first) && (flags & V_SAVEMETA))
  			while (blist && blist->b_lblkno < 0)
  				blist = blist->b_vnbufs.le_next;
***************
*** 502,510 ****
  				error = tsleep((caddr_t) bp,
  				    slpflag | (PRIBIO + 1), "vinvalbuf",
  				    slptimeo);
! 				splx(s);
! 				if (error)
  					return (error);
  				break;
  			}
  			bremfree(bp);
--- 502,511 ----
  				error = tsleep((caddr_t) bp,
  				    slpflag | (PRIBIO + 1), "vinvalbuf",
  				    slptimeo);
! 				if (error) {
! 					splx(s);
  					return (error);
+ 				}
  				break;
  			}
  			bremfree(bp);
***************
*** 522,527 ****
--- 523,529 ----
  			bp->b_flags |= (B_INVAL|B_NOCACHE|B_RELBUF);
  			brelse(bp);
  		}
+ 		splx(s);
  	}
  	splx(s);
  
>Release-Note:
>Audit-Trail:

From: David Greenman <dg@root.com>
To: kato@eclogite.eps.nagoya-u.ac.jp
Cc: FreeBSD-gnats-submit@FreeBSD.org
Subject: Re: kern/2875: vinvalbuf() clobbers b_vnbufs chain 
Date: Tue, 04 Mar 1997 12:21:09 -0800

    Hmmm, the fix seems overly complicated. How about this instead:
 
 Index: vfs_subr.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/kern/vfs_subr.c,v
 retrieving revision 1.64.2.2
 diff -c -r1.64.2.2 vfs_subr.c
 *** vfs_subr.c	1997/02/28 11:11:50	1.64.2.2
 --- vfs_subr.c	1997/03/04 20:17:51
 ***************
 *** 502,510 ****
   				error = tsleep((caddr_t) bp,
   				    slpflag | (PRIBIO + 1), "vinvalbuf",
   				    slptimeo);
 ! 				splx(s);
 ! 				if (error)
   					return (error);
   				break;
   			}
   			bremfree(bp);
 --- 502,511 ----
   				error = tsleep((caddr_t) bp,
   				    slpflag | (PRIBIO + 1), "vinvalbuf",
   				    slptimeo);
 ! 				if (error) {
 ! 					splx(s);
   					return (error);
 + 				}
   				break;
   			}
   			bremfree(bp);
 ***************
 *** 523,535 ****
   			brelse(bp);
   		}
   	}
 - 	splx(s);
   
 - 	s = splbio();
   	while (vp->v_numoutput > 0) {
   		vp->v_flag |= VBWAIT;
   		tsleep(&vp->v_numoutput, PVM, "vnvlbv", 0);
   	}
   	splx(s);
   
   	/*
 --- 524,535 ----
   			brelse(bp);
   		}
   	}
   
   	while (vp->v_numoutput > 0) {
   		vp->v_flag |= VBWAIT;
   		tsleep(&vp->v_numoutput, PVM, "vnvlbv", 0);
   	}
 + 
   	splx(s);
   
   	/*
 
 -DG
 
 David Greenman
 Core-team/Principal Architect, The FreeBSD Project

From: KATO Takenori <kato@eclogite.eps.nagoya-u.ac.jp>
To: dg@root.com
Cc: FreeBSD-gnats-submit@FreeBSD.org
Subject: Re: kern/2875: vinvalbuf() clobbers b_vnbufs chain 
Date: Wed, 05 Mar 1997 11:28:44 +0900

 From: David Greenman <dg@root.com>
 Subject: Re: kern/2875: vinvalbuf() clobbers b_vnbufs chain 
 Date: Tue, 04 Mar 1997 12:21:09 -0800
 
 >    Hmmm, the fix seems overly complicated. How about this instead:
 
 Your fix inhibit disk I/O interruption for more long time.  If this
 is not a problem, I prefer your fix.
 
 
 ----
 KATO Takenori <kato@eclogite.eps.nagoya-u.ac.jp>
 Dept. Earth Planet. Sci., Nagoya Univ.,  Nagoya, 464-01, Japan
 PGP public key: finger kato@eclogite.eps.nagoya-u.ac.jp
 ------------------- Powered by FreeBSD(98) -------------------

From: David Greenman <dg@root.com>
To: KATO Takenori <kato@eclogite.eps.nagoya-u.ac.jp>
Cc: FreeBSD-gnats-submit@FreeBSD.org
Subject: Re: kern/2875: vinvalbuf() clobbers b_vnbufs chain 
Date: Tue, 04 Mar 1997 18:54:04 -0800

 >From: David Greenman <dg@root.com>
 >Subject: Re: kern/2875: vinvalbuf() clobbers b_vnbufs chain 
 >Date: Tue, 04 Mar 1997 12:21:09 -0800
 >
 >>    Hmmm, the fix seems overly complicated. How about this instead:
 >
 >Your fix inhibit disk I/O interruption for more long time.  If this
 >is not a problem, I prefer your fix.
 
    I don't think it's a problem. The actual delay is fairly low in practice
 (probably less than 50us), and letting an interrupt through prior to the
 check for v_numoutput/tsleep isn't likely going to be of benefit (I/O due
 to the sync operations would not likely have completed yet). John is welcome
 to correct me if he thinks I'm in error...
 
 -DG
 
 David Greenman
 Core-team/Principal Architect, The FreeBSD Project
State-Changed-From-To: open->closed 
State-Changed-By: davidg 
State-Changed-When: Tue Mar 4 21:03:15 PST 1997 
State-Changed-Why:  
Thanks for the bug report. I've fixed the bug in rev 1.80 of 
vfs_subr.c and brought the fix into the 2.2 branch. 
>Unformatted:
