Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Apr 1999 06:43:48 -0700 (PDT)
From:      smcclure@emc.com
To:        freebsd-gnats-submit@freebsd.org
Subject:   kern/11366: Filesystem can cause hang/crash in certain situations
Message-ID:  <19990428134348.031E714DC4@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         11366
>Category:       kern
>Synopsis:       Filesystem can cause hang/crash in certain situations
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Apr 28 06:50:00 PDT 1999
>Closed-Date:
>Last-Modified:
>Originator:     Steve McClure
>Release:        3.1 Release
>Organization:
EMC Corporation
>Environment:
FreeBSD lbn1050.lss.emc.com 3.1-RELEASE FreeBSD 3.1-RELEASE #7: Tue Apr 27 14:43:51 GMT 1999     smcclure@lbn1050.lss.emc.com:/usr/src/sys/compile/COMPAQ.AP200  i386
>Description:
Hello.  I think I have found a bug in the UFS filesystem code in
ufs_lookup.c that can cause the kernel to hang/crash in certain 
situations.

(Note this is coming from the 3.1 release code.  If this has been
fixed, sorry, but I couldn't find any report of it.)

On line 238 this assignment is made:
		
   ep = (struct direct *)((char *)bp->b_data + entryoffsetinblock);

This pointer is then used during the lookup of directory entry names
while looking for a specific entry.

On line 311, if we have actually found the entry we are looking for,
we save the inode and the record length, and then do a brelse of bp.
I.E. we release the buffer that the ep pointer is pointing to.

We then jump to the "found" label.

The found label is on line 405.  On line 412, we do this check:

   if (entryoffsetinblock + DIRSIZ(OFSFMT(vdp), ep) > dp->i_size) {

I have found that this can cause problems because we are using a pointer
to a buffer that now may contain garbage or not even exist anymore (if
we managed to get interrupted between here and there and the buffer
gets used by someone else.)  It only happens under extreme circumstances
in ufs.

Note that I found this problem while working on a variation of the
ufs filesystem, where timing was more critical (as in the buffer would
always be released before we got to the pointer use again) but it can
still be a big problem.

I'm not sure if this exists in any of the other filesystems or not.



>How-To-Repeat:
Under standard ufs, it's very hard to get it to repeat reliably (in fact
I think I've only seen it twice under extremely heavy load in very
"weird" circumstances, but not even sure if it was this.)  I was able
to verify it using a variation of brelse that makes sure the buffer
is released before returning.
>Fix:
My solution to this was to release the buffer *after* this check.

On line 313, I took out the "brelse(bp);" call.

On line 334 there is this code:

  if (bp != NULL)
	brelse(bp);

I also put this below the bad entry check to release bp after the
check has been done and we are done with the buffer.


>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19990428134348.031E714DC4>