Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 29 May 2006 17:40:19 GMT
From:      Bruce Evans <bde@zeta.org.au>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/98064: Crash with FIFOs (named pipes) and truncate()
Message-ID:  <200605291740.k4THeJPX067839@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/98064; it has been noted by GNATS.

From: Bruce Evans <bde@zeta.org.au>
To: Maxim Konovalov <maxim@macomnet.ru>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: kern/98064: Crash with FIFOs (named pipes) and truncate()
Date: Tue, 30 May 2006 03:38:55 +1000 (EST)

 On Mon, 29 May 2006, Maxim Konovalov wrote:
 
 > On Tue, 30 May 2006, 00:04+1000, Bruce Evans wrote:
 >
 > > On Mon, 29 May 2006, Maxim Konovalov wrote:
 
 > > > Why doesn't RELENG_4 suffer from this?  The code of ufs_setattr() is
 > > > very similar there.
 > >
 > > Hmm, my fixes are for ~5.2 and they may be unnecessary there too.  I don't
 > > remember noticing this particular problem.  Perhaps some changes in -current
 > > resulted in ffs_update() doing more and happening to do something bad.
 > > Unfortunately, the PR doesn't contain much debugging info so it isn't
 > > clear that the problem is in ffs_update().
 >
 > Here is a backtrace:
 >
 > Unread portion of the kernel message buffer:
 > No strategy for buffer at 0xcc6a8b70
 > vnode
 > 0xc2c6c514: tag ufs, type VFIFO
 >     usecount 1, writecount 0, refcount 2 mountedhere 0
 >     flags ()
 >      lock type ufs: EXCL (count 1) by thread 0xc28ca6c0 (pid 1039)
 > 	ino 141854, on dev ad0s1e
 > ...
 > #10 0xc05bf3bd in trap (frame=
 >       {tf_fs = -1027211256, tf_es = 65576, tf_ds = -714801112, tf_edi = 67584, tf_esi = -1027160812, tf_ebp = -714737768, tf_isp = -714737788, tf_ebx = -1027336392, tf_edx = 0, tf_ecx = -1056878592, tf_eax = 0, tf_trapno = 12, tf_err = 0, tf_eip = -1069035627, tf_cs = 32, tf_eflags = 590406, tf_esp = -714737748, tf_ss = -1068030820}) at /usr/src/sys/i386/i386/trap.c:463
 > #11 0xc05b035a in calltrap () at /usr/src/sys/i386/i386/exception.s:138
 > ---Type <return> to continue, or q <return> to quit---
 > #12 0xc047cf95 in fifo_printinfo (vp=0x0)
 >     at /usr/src/sys/fs/fifofs/fifo_vnops.c:448
 > #13 0xc057249c in ufs_print (ap=0x0) at /usr/src/sys/ufs/ufs/ufs_vnops.c:1965
 > #14 0xc05d1c70 in VOP_PRINT_APV (vop=0x0, a=0xd565f7cc) at vnode_if.c:1899
 > #15 0xc050cafa in vn_printf (vp=0xc2c6c514, fmt=0xc05e2816 "%s\n")
 >     at vnode_if.h:971
 > #16 0xc0502a4e in vop_nostrategy (ap=0xd565f8a8)
 >     at /usr/src/sys/kern/vfs_default.c:195
 
 It has paniced in the debugging code in vop_nostrategy().  That code
 is apparently broken.  vop_nostrategy() starts with a printf() that
 works.  It then calls vprint() which panics.  ap=0x0 in ufs_print and
 vp=0x0 in fifo_printinfo() seem to have been corrupted between printing
 some info about the fifo and panicing.  Instead of panicing, vprint()
 is supposed to return.  Then vop_nostrategy() is supposed to do nothing
 except fail the i/o.
 
 > #17 0xc05d1b05 in VOP_STRATEGY_APV (vop=0xc062a280, a=0xd565f8a8)
 >     at vnode_if.c:1797
 > #18 0xc0568920 in ffsext_strategy (ap=0xd565f8a8)
 >     at /usr/src/sys/ufs/ffs/ffs_vnops.c:1291
 > #19 0xc05d1b05 in VOP_STRATEGY_APV (vop=0xc0631520, a=0xd565f8a8)
 >     at vnode_if.c:1797
 > #20 0xc04ff6fd in bufstrategy (bo=0x0, bp=0xcc6a8b70) at vnode_if.h:928
 > #21 0xc04fa81e in bufwrite (bp=0xcc6a8b70) at buf.h:419
 
 ffs_truncate() has done bad things to reach here.  It has reached the
 "Lengthen the size of the file" code and succeeded in allocating some
 blocks, despite the fifo file type not being capable of having any blocks.
 Perhaps the allocation works because the blocks are virtual and no indirect
 blocks are required.  The test program only allocates 16K IIRC, and that
 many virtual blocks are represented as 0's in the inode alone.  A larger
 extension might cause more problems by allocating indirect blocks.
 
 Now ffs_truncate() is trying to write the buffer for which it has just
 allocated blocks.  The write is done via vop_nostrategy() which should
 just fail.  I suppose the write would be null for the case of all blocks
 virtual if it were done by a non-null strategy routine.
 
 ffs_truncate() continues to do bad things by not checking for errors in
 the write even for the IO_SYNC case where the write function returns
 an error.  ffs_truncate() has committed to the write succeeding, and has
 updated the size in the in-core inode.
 
 > #22 0xc04fae51 in bawrite (bp=0x0) at buf.h:405
 > #23 0xc0552581 in ffs_truncate (vp=0xc2c6c514, length=16000, flags=67584,
 >     cred=0xc2be3e80, td=0xc28ca6c0) at /usr/src/sys/ufs/ffs/ffs_inode.c:304
 > #24 0xc056ffe9 in ufs_setattr (ap=0x0) at /usr/src/sys/ufs/ufs/ufs_vnops.c:532
 > #25 0xc05d0ae6 in VOP_SETATTR_APV (vop=0x0, a=0xd565fb3c) at vnode_if.c:586
 > #26 0xc0513195 in kern_truncate (td=0xc28ca6c0, path=0x0,
 >     pathseg=UIO_USERSPACE, length=16000) at vnode_if.h:314
 > ---Type <return> to continue, or q <return> to quit---
 > #27 0xc0512fac in truncate (td=0xc28ca6c0, uap=0x0)
 >     at /usr/src/sys/kern/vfs_syscalls.c:3018
 
 This may explain why RELENG_4 doesn't panic.  The ufs and ffs layers might
 do the same bad things without anyone noticing if the debugging code doesn't
 panic or if the wrong strategy routine is used.  You can tell if the wrong
 strategy routine is used by checking for debugging output.  vop_strategy()
 hasn't changed much, but the plumbing for strategy routines has.  Larger
 extensions might cause more obvious problems in RELENG_4 too.  If I'm right,
 then the bugs would also show up as fifos with a nonzero size (st_size in
 struct stat?) and maybe as allocated unwriteable physical blocks for sizes
 that require indirect blocks.
 
 Anyway, the fix is to return (0) long before reaching "Lengthen the size
 of the file" in ffs_truncate().
 
 Bruce



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