Date: 13 May 1998 12:01:51 +0100 From: Simon Marlow <simonm@dcs.gla.ac.uk> To: freebsd-bugs@FreeBSD.ORG Subject: Re: kern/6611: nfs_inactive can write through a dangling pointer and corrupt memory. Message-ID: <t6zpgm1ljz.fsf@solander.dcs.gla.ac.uk> In-Reply-To: stephen clawson's message of Tue, 12 May 1998 18:19:25 -0600 (MDT) References: <199805130019.SAA16560@marker.cs.utah.edu>
next in thread | previous in thread | raw e-mail | index | archive | help
stephen clawson <sclawson@marker.cs.utah.edu> writes:
> The pattern of damage is such that the upper short of the 6th
> direct block pointer gets anded with 0x00e7 (~0xff18).
And this could be part of a symbolic link, if the link is stored in
the inode, couldn't it? If so, I've seen this: it shows up quite
easily by doing a large lndir. I quite often get corrupted links,
with the corruption matching what Steven says above.
Thanks Steven!
>
>
> >How-To-Repeat:
>
> My standard workload included:
>
> cvs checkout cycle (from an nfs mounted cvs root tree)
> large build (gdb-4.17)
> create/remove lots (100-1000) of 64k+ files (so they've
> actually got a 6th block pointer).
>
> These are done both on a local filesystem and an nfs mounted
> filesystem, so there are a total of 6 things going on. All of them
> just keep cycling (cvs checkout/rm, make/make clean, etc.). Usually
> it takes about 20-30 minutes for the problem to show up.
>
> What makes detecting it difficult is that there's nothing that
> directly breaks when the corruption occurs. You only notice it if you
> happen to remove a corrupt file and get a ``freeing free block''
> panic, or you reboot and happen to fsck the filesystem with the
> problem (in which case fsc will tell you about the DUP allocation,
> assuming that the corrupt direct block is pointing into an allocated
> block and not free space).
>
> To notice when the corruption was occuring, I added code to the
> kernel to shadow the di_db[5] into di_spare[0] and periodically
> checked to see if di_db[5] had changed.
>
>
> >Fix:
>
> The simple fix is to grab an extra reference to the vnode if
> there's a possiblilty that we might block. It's pretty heavy-handed,
> since it vget dosen't just remove the vnode from the free list, it
> also allocates a vm_object for it that will just get destroyed
> when we do a vrele on it later. =(
>
> Alternately, the nfs code could actually do locking on it's
> nfsnode's, but since that code still isn't done in -current... =)
> Or, you could muck with the vnode freelist directly. Anything that
> prevents the nfsnode from being free'd before nfs_inactive is done
> with it.
>
> NetBSD incorporated the same fix (apparently given to them
> from BSDI) a while ago. They only grab a reference for the call
> to nfs_vinvalbuf though, in the case of -stable, nfs_removeit can
> also block, so I just grab the reference for the entire sillyrename
> code section. See NetBSD-current (1.3.1 should have it)
> sys/nfs/nfs_node.c:nfs_inactive.
>
>
> diff -c -r1.13.2.1 nfs_node.c
> *** nfs_node.c 1997/05/14 08:19:27 1.13.2.1
> --- nfs_node.c 1998/05/11 17:59:21
> ***************
> *** 202,207 ****
> --- 202,215 ----
> } else
> sp = (struct sillyrename *)0;
> if (sp) {
> + /*
> + * We need a reference to keep the vnode from being
> + * recycled by getnewvnode while we do the I/O
> + * associated with discarding the buffers.
> + */
> + if (vget(ap->a_vp, 0))
> + panic("nfs_inactive: lost vnode");
> +
> /*
> * Remove the silly file that was rename'd earlier
> */
> ***************
> *** 210,215 ****
> --- 218,228 ----
> crfree(sp->s_cred);
> vrele(sp->s_dvp);
> FREE((caddr_t)sp, M_NFSREQ);
> +
> + /* XXX Play it safe and release our reference
> + * after we're done.
> + */
> + vrele(ap->a_vp);
> }
> np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
> NQNFSNONCACHE | NQNFSWRITE);
>
>
> >Audit-Trail:
> >Unformatted:
>
> To Unsubscribe: send mail to majordomo@FreeBSD.org
> with "unsubscribe freebsd-bugs" in the body of the message
>
--
--
Simon Marlow simonm@dcs.gla.ac.uk
University of Glasgow http://www.dcs.gla.ac.uk/~simonm/
finger for PGP public key
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?t6zpgm1ljz.fsf>
