Date: Tue, 16 Aug 2005 12:42:25 +0300 (EEST) From: Andriy Gapon <avg@icyb.net.ua> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/84983: udf filesystem: stat-ting files could randomly fail Message-ID: <200508160942.j7G9gPJe054914@oddity.topspin.kiev.ua> Resent-Message-ID: <200508160950.j7G9oMJZ096235@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 84983 >Category: kern >Synopsis: udf filesystem: stat-ting files could randomly fail >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Aug 16 09:50:21 GMT 2005 >Closed-Date: >Last-Modified: >Originator: Andriy Gapon >Release: FreeBSD 5.4-RELEASE-p3 i386 >Organization: >Environment: System: FreeBSD 5.4-RELEASE-p3 #3: Sat Jul 9 17:02:15 EEST 2005 i386 >Description: Sometimes stat(2) on files located on UDF fs unexpectedly fails, at the same time "udf: invalid FID fragment" kernel messages are produced. umount+mount in such situation usually cures the problem, but sometimes I have to do kldunload udf in between. The symptom very much looks like use of unitialized variable/memory. Brief search for a culprit made me suspect udf_node.diroff field. This is how udf_node structures are allocated: udf_vfsops.c: struct udf_node *unode; ... unode = uma_zalloc(udf_zone_node, M_WAITOK); i.e. there is no M_ZERO while allocating udf_node and diroff field does not seem to be initialized explicitely: $ fgrep diroff *.[ch] udf.h: long diroff; udf_vnops.c: if (nameiop != LOOKUP || node->diroff == 0 || node->diroff > fsize) { udf_vnops.c: offset = node->diroff; udf_vnops.c: node->diroff = ds->offset + ds->off; as you can see diroff could be used before it is assigned and it is used in udf_lookup() function as follows: if (nameiop != LOOKUP || node->diroff == 0 || node->diroff > fsize) { offset = 0; numdirpasses = 1; } else { offset = node->diroff; numdirpasses = 2; nchstats.ncs_2passes++; } lookloop: ds = udf_opendir(node, offset, fsize, udfmp); as you can see, if diroff belongs to interval (0, fsize] and nameiop is LOOKUP, then offset variable will be assigned with its (random) value that, in turn, would be passed down to udf_opendir and, thus, directory stream would contain incorrect (arbitrary) data. >How-To-Repeat: because of probabalistic nature of the bug, there is no definite recipe of reproducing it. you could try to do a lot of operations (ls, stat) on files on UDF fs and see if eventually directory udf_node will be allocated with "good" junk at diroff position. for me, this happens from time to time on its own. >Fix: if my theory is correct, then the following patch should fix the problem by adding proper initialization to diroff field of udf_node: --- lookup.patch begins here --- --- sys/fs/udf/udf_vfsops.c.orig Mon Aug 15 21:06:50 2005 +++ sys/fs/udf/udf_vfsops.c Mon Aug 15 21:07:07 2005 @@ -648,6 +648,7 @@ return (error); } + unode->diroff = 0; unode->i_vnode = vp; unode->hash_id = ino; unode->i_devvp = udfmp->im_devvp; --- lookup.patch ends here --- >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200508160942.j7G9gPJe054914>