From: Anand Avati <avati@redhat.com>
To: miklos@szeredi.hu
Cc: linux-fsdevel@vger.kernel.org, fuse-devel@lists.sourceforge.net
Subject: [PATCH] fuse: mark all aliases of an inode stale in unlink
Date: Fri, 20 Jan 2012 03:16:12 +0530 [thread overview]
Message-ID: <20120119214611.GA18553@blackhole.redhat.com> (raw)
Problem:
create("filename") => 0
link("filename", "linkname") => 0
unlink("filename") => 0
link("linkname", "filename") => -ENOENT ### BUG ###
This is a test case link section of the Poix compliance test suite from
ntfs-3g project.
Cause:
fuse_unlink() clears i_nlink of the inode. If the inode has
hardlinks (and hence aliases) they kept fresh (within the entry
timeout bounds.) A link() call happening right after unlink now checks
for i_nlink == 0 (since patch aae8a97d3ec30788790d1720b71d76fd8eb44b73)
and fails the syscall for security reasons.
Fix:
Instead of marking the just-unlinked entry as stale, mark all
the aliases as stale so that a revalidation of the alias is done during
path resolution.
Signed-off-by: Anand Avati <avati@redhat.com>
---
fs/fuse/dir.c | 21 ++++++++++++++++++++-
1 files changed, 20 insertions(+), 1 deletions(-)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 2066328..880e9dd 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -103,6 +103,25 @@ void fuse_invalidate_entry_cache(struct dentry *entry)
}
/*
+ * Mark all dentry aliases of an inode as stale. It is necessary to mark
+ * all aliases as stale because a link() on an inode performed right
+ * after an unlink on one of the hardlinks will pick the inode without
+ * a revalidate and find i_nlink == 0. This ends up getting checked as
+ * a security vulnerability and fail -ENOENT. Marking all aliases as stale
+ * will instead force lookup the inode freshly at the time of link()
+ */
+void fuse_invalidate_all_aliases(struct inode *inode)
+{
+ struct dentry *alias;
+
+ spin_lock(&inode->i_lock);
+ list_for_each_entry(alias, &inode->i_dentry, d_alias) {
+ fuse_invalidate_entry_cache(alias);
+ }
+ spin_unlock(&inode->i_lock);
+}
+
+/*
* Same as fuse_invalidate_entry_cache(), but also try to remove the
* dentry from the hash
*/
@@ -653,7 +672,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
clear_nlink(inode);
fuse_invalidate_attr(inode);
fuse_invalidate_attr(dir);
- fuse_invalidate_entry_cache(entry);
+ fuse_invalidate_all_aliases(inode);
} else if (err == -EINTR)
fuse_invalidate_entry(entry);
return err;
--
1.7.6.4
--
"It's easier said than done."
... and if you don't believe it, try proving that it's easier done than
said, and you'll see that "it's easier said that `it's easier done than
said' than it is done", which really proves that "it's easier said than
done".
next reply other threads:[~2012-01-19 22:45 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-01-19 21:46 Anand Avati [this message]
-- strict thread matches above, loose matches on Subject: below --
2012-01-19 21:56 [PATCH] fuse: mark all aliases of an inode stale in unlink Anand Avati
2012-01-20 14:40 ` Miklos Szeredi
2012-01-20 15:24 ` Anand Avati
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=20120119214611.GA18553@blackhole.redhat.com \
--to=avati@redhat.com \
--cc=fuse-devel@lists.sourceforge.net \
--cc=linux-fsdevel@vger.kernel.org \
--cc=miklos@szeredi.hu \
/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.