From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
To: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Richard Weinberger <richard@nod.at>,
Sami Liedes <sami.liedes@iki.fi>,
linux-fsdevel <linux-fsdevel@vger.kernel.org>
Subject: Re: Intentionally corrupted vfat fs causing BUG
Date: Fri, 24 Oct 2014 02:58:05 +0900 [thread overview]
Message-ID: <87oat27jo2.fsf@devron.myhome.or.jp> (raw)
In-Reply-To: <20141023172158.GF7996@ZenIV.linux.org.uk> (Al Viro's message of "Thu, 23 Oct 2014 18:21:58 +0100")
Al Viro <viro@ZenIV.linux.org.uk> writes:
> On Thu, Oct 23, 2014 at 05:55:33PM +0100, Al Viro wrote:
>> On Fri, Oct 24, 2014 at 01:45:49AM +0900, OGAWA Hirofumi wrote:
>>
>> > d_splice_alias() calls __d_find_alias() with want_discon==1, so
>> > __d_find_alias() doesn't return dentry, and d_splice_alias() doesn't use
>> > d_move() path, right?
>>
>> Hmm... Not in the current mainline (and not because of want_discon - that's
>> gone already). However, with the fixes I've got in the local tree it
>> will both find and move it - same as d_materialise_unique() would in the
>> current mainline.
>
> Untested interim fix follows; as soon as d_splice_alias()/d_materialise_unique()
> merge happens, we'll be able to clean vfat_lookup() a bit more.
>
> a) don't bother with ->d_time for positives - we only check it for negatives
> anyway.
> b) make sure to set it at unlink and rmdir time - at *that* point soon-to-be
> negative dentry matches then-current directory contents
> c) don't go into renaming of old alias in vfat_lookup() unless it has
> the same parent (which it will, unless we are seeing corrupted image) *and*
> is a non-directory
> d) use (for now) d_materialise_unique() instead of d_splice_alias() - that one
> will do renames of old directory aliases just fine (and pretty soon so will
> d_splice_alias(), but this bug is -stable fodder)
Ah, this calls d_move() for directory?
I recalled why it didn't change alias if directory. Changing result of
getcwd() may become the surprise of apps... If doesn't surprise, looks
good.
> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> ---
> diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
> index 6df8d3d..eed856f 100644
> --- a/fs/fat/namei_vfat.c
> +++ b/fs/fat/namei_vfat.c
> @@ -736,17 +736,17 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
> }
>
> alias = d_find_alias(inode);
> - if (alias && !vfat_d_anon_disconn(alias)) {
> + if (alias && alias->d_parent == dentry->d_parent &&
> + !S_ISDIR(inode->i_mode) && !vfat_d_anon_disconn(alias)) {
> /*
> - * This inode has non anonymous-DCACHE_DISCONNECTED
> + * This file has non anonymous-DCACHE_DISCONNECTED
> * dentry. This means, the user did ->lookup() by an
> * another name (longname vs 8.3 alias of it) in past.
> *
> * Switch to new one for reason of locality if possible.
> */
> BUG_ON(d_unhashed(alias));
> - if (!S_ISDIR(inode->i_mode))
> - d_move(alias, dentry);
> + d_move(alias, dentry);
> iput(inode);
> mutex_unlock(&MSDOS_SB(sb)->s_lock);
> return alias;
> @@ -755,12 +755,9 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
>
> out:
> mutex_unlock(&MSDOS_SB(sb)->s_lock);
> - dentry->d_time = dentry->d_parent->d_inode->i_version;
> - dentry = d_splice_alias(inode, dentry);
> - if (dentry)
> - dentry->d_time = dentry->d_parent->d_inode->i_version;
> - return dentry;
> -
> + if (!inode)
> + dentry->d_time = dir->i_version;
> + return d_materialise_unique(dentry, inode);
> error:
> mutex_unlock(&MSDOS_SB(sb)->s_lock);
> return ERR_PTR(err);
> @@ -793,7 +790,6 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
> inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
> /* timestamp is already written, so mark_inode_dirty() is unneeded. */
>
> - dentry->d_time = dentry->d_parent->d_inode->i_version;
> d_instantiate(dentry, inode);
> out:
> mutex_unlock(&MSDOS_SB(sb)->s_lock);
> @@ -824,6 +820,7 @@ static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
> clear_nlink(inode);
> inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
> fat_detach(inode);
> + dentry->d_time = dir->i_version;
> out:
> mutex_unlock(&MSDOS_SB(sb)->s_lock);
>
> @@ -849,6 +846,7 @@ static int vfat_unlink(struct inode *dir, struct dentry *dentry)
> clear_nlink(inode);
> inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
> fat_detach(inode);
> + dentry->d_time = dir->i_version;
> out:
> mutex_unlock(&MSDOS_SB(sb)->s_lock);
>
> @@ -889,7 +887,6 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
> inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
> /* timestamp is already written, so mark_inode_dirty() is unneeded. */
>
> - dentry->d_time = dentry->d_parent->d_inode->i_version;
> d_instantiate(dentry, inode);
>
> mutex_unlock(&MSDOS_SB(sb)->s_lock);
--
OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
next prev parent reply other threads:[~2014-10-23 17:58 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-10 20:57 Intentionally corrupted vfat fs causing BUG Sami Liedes
2014-10-11 10:20 ` Richard Weinberger
2014-10-12 12:08 ` OGAWA Hirofumi
2014-10-12 19:04 ` Richard Weinberger
2014-10-12 20:40 ` Sami Liedes
2014-10-13 7:57 ` OGAWA Hirofumi
2014-10-13 8:22 ` Richard Weinberger
2014-10-13 8:35 ` OGAWA Hirofumi
2014-10-13 8:39 ` Richard Weinberger
2014-10-13 8:59 ` OGAWA Hirofumi
2014-10-13 14:36 ` Richard Weinberger
2014-10-19 16:36 ` Richard Weinberger
2014-10-23 15:28 ` OGAWA Hirofumi
2014-10-23 16:01 ` Al Viro
2014-10-23 16:16 ` Al Viro
2014-10-23 16:45 ` OGAWA Hirofumi
2014-10-23 16:50 ` OGAWA Hirofumi
2014-10-23 16:55 ` Richard Weinberger
2014-10-23 16:55 ` Al Viro
2014-10-23 17:21 ` Al Viro
2014-10-23 17:58 ` OGAWA Hirofumi [this message]
2014-10-23 20:46 ` Sami Liedes
2014-10-23 17:35 ` OGAWA Hirofumi
2014-10-23 17:54 ` J. Bruce Fields
2014-10-23 18:05 ` Al Viro
2014-10-23 18:16 ` J. Bruce Fields
2014-10-23 16:56 ` Al Viro
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87oat27jo2.fsf@devron.myhome.or.jp \
--to=hirofumi@mail.parknet.co.jp \
--cc=linux-fsdevel@vger.kernel.org \
--cc=richard@nod.at \
--cc=sami.liedes@iki.fi \
--cc=viro@ZenIV.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.