linux-xfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Darrick J. Wong" <darrick.wong@oracle.com>
To: xfs <linux-xfs@vger.kernel.org>
Subject: [PATCH] xfs: allow zero-length symlinks (and directories), sort of
Date: Fri, 3 Mar 2017 16:05:29 -0800	[thread overview]
Message-ID: <20170304000529.GB5073@birch.djwong.org> (raw)

In commit ef388e2054 ("don't allow di_size with high bit set") and
commit 3c6f46eacd87 ("sanity check directory inode di_size") we
erroneously fail the inode verification checks for symlinks or
directories with di_size == 0.

This is proven incorrect by generic/388 because the unlink process uses
multiple unconnected transactions to truncate the remote symlink /
directory and to unlink and free the inode.  If the fs goes down after
the truncate commit but before the unlink happens, we are left with a
zero-length inode.  Worse yet, if the unlink /does/ commit, log recovery
will now break after the first transaction because we've zeroed di_size.

In order to prevent the crashes and ASSERTs that the old patches
covered, re-allow the zero-length inodes and change the functions that
interface with the vfs to return the appropriate error codes to
userspace.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/libxfs/xfs_inode_buf.c |    4 ----
 fs/xfs/xfs_dir2_readdir.c     |    6 ++----
 fs/xfs/xfs_iops.c             |    9 ++++++++-
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 3752bac..6e62999 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -402,10 +402,6 @@ xfs_dinode_verify(
 	if (mode && xfs_mode_to_ftype(mode) == XFS_DIR3_FT_UNKNOWN)
 		return false;
 
-	/* No zero-length symlinks/dirs. */
-	if ((S_ISLNK(mode) || S_ISDIR(mode)) && dip->di_size == 0)
-		return false;
-
 	/* only version 3 or greater inodes are extensively verified here */
 	if (dip->di_version < 3)
 		return true;
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c
index 0b3b636..be1367a 100644
--- a/fs/xfs/xfs_dir2_readdir.c
+++ b/fs/xfs/xfs_dir2_readdir.c
@@ -74,10 +74,8 @@ xfs_dir2_sf_getdents(
 	/*
 	 * Give up if the directory is way too short.
 	 */
-	if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
-		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
-		return -EIO;
-	}
+	if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent))
+		return -EFSCORRUPTED;
 
 	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
 	ASSERT(dp->i_df.if_u1.if_data != NULL);
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 22c1615..b7b6807 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -457,6 +457,9 @@ xfs_vn_get_link(
 	char			*link;
 	int			error = -ENOMEM;
 
+	if (i_size_read(inode) == 0)
+		return ERR_PTR(-EFSCORRUPTED);
+
 	if (!dentry)
 		return ERR_PTR(-ECHILD);
 
@@ -483,8 +486,12 @@ xfs_vn_get_link_inline(
 	struct inode		*inode,
 	struct delayed_call	*done)
 {
+	char			*p;
 	ASSERT(XFS_I(inode)->i_df.if_flags & XFS_IFINLINE);
-	return XFS_I(inode)->i_df.if_u1.if_data;
+	p = XFS_I(inode)->i_df.if_u1.if_data;
+	if (p)
+		return p;
+	return ERR_PTR(-EFSCORRUPTED);
 }
 
 STATIC int

             reply	other threads:[~2017-03-04  0:06 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-04  0:05 Darrick J. Wong [this message]
2017-03-06 13:51 ` [PATCH] xfs: allow zero-length symlinks (and directories), sort of Brian Foster
2017-03-06 17:22   ` Darrick J. Wong
2017-03-06 18:18     ` Brian Foster
2017-03-06 21:47       ` Dave Chinner
2017-03-06 23:16         ` Darrick J. Wong

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=20170304000529.GB5073@birch.djwong.org \
    --to=darrick.wong@oracle.com \
    --cc=linux-xfs@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).