All of lore.kernel.org
 help / color / mirror / Atom feed
From: Anand Avati <avati@redhat.com>
To: miklos@szeredi.hu
Cc: linux-fsdevel@vger.kernel.org, fuse-devel@lists.sourceforge.net,
	josef@redhat.com, chenk@redhat.com
Subject: [PATCH] fuse: mark all aliases of an inode stale in unlink
Date: Thu, 19 Jan 2012 16:56:49 -0500	[thread overview]
Message-ID: <20120119215649.GA19933@shell.devel.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


             reply	other threads:[~2012-01-19 21:56 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-19 21:56 Anand Avati [this message]
2012-01-20 14:40 ` [PATCH] fuse: mark all aliases of an inode stale in unlink Miklos Szeredi
2012-01-20 15:24   ` Anand Avati
  -- strict thread matches above, loose matches on Subject: below --
2012-01-19 21:46 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=20120119215649.GA19933@shell.devel.redhat.com \
    --to=avati@redhat.com \
    --cc=chenk@redhat.com \
    --cc=fuse-devel@lists.sourceforge.net \
    --cc=josef@redhat.com \
    --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.