All of lore.kernel.org
 help / color / mirror / Atom feed
From: Amir Goldstein <amir73il@gmail.com>
To: Miklos Szeredi <miklos@szeredi.hu>
Cc: Al Viro <viro@zeniv.linux.org.uk>,
	Vivek Goyal <vgoyal@redhat.com>,
	linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org
Subject: [PATCH v3 4/4] ovl: make ovl_create_real() cope with vfs_mkdir() safely
Date: Tue, 15 May 2018 13:26:12 +0300	[thread overview]
Message-ID: <1526379972-20923-5-git-send-email-amir73il@gmail.com> (raw)
In-Reply-To: <1526379972-20923-1-git-send-email-amir73il@gmail.com>

From: Al Viro <viro@zeniv.linux.org.uk>

vfs_mkdir() may succeed and leave the dentry passed to it unhashed and
negative.  ovl_create_real() is the last caller breaking when that
happens.

Pass newdentry to ovl_create_real() by ref, so in the case above, if
lookup finds a good dentry, newdentry will be replaced by the positive
hashed one.

[amir: split re-factoring to prep patch
       pass dentry by ref
       factor out helper ovl_create_real_dir()
       add pr_warn() if mkdir succeeds and lookup fails]

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
 fs/overlayfs/dir.c       | 42 +++++++++++++++++++++++++++++++++++++-----
 fs/overlayfs/overlayfs.h |  2 +-
 fs/overlayfs/super.c     |  2 +-
 3 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 45f5f9232e71..a90328c41307 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -114,9 +114,41 @@ int ovl_cleanup_and_whiteout(struct dentry *workdir, struct inode *dir,
 	goto out;
 }
 
-int ovl_create_real(struct inode *dir, struct dentry *newdentry,
+static int ovl_create_real_dir(struct inode *dir, struct dentry **pnewdentry,
+			       umode_t mode)
+{
+	struct dentry *newdentry = *pnewdentry;
+	int err;
+
+	err = ovl_do_mkdir(dir, newdentry, mode, true);
+	/*
+	 * vfs_mkdir() may succeed and leave the dentry passed
+	 * to it unhashed and negative. If that happens, try to
+	 * lookup a new hashed and positive dentry.
+	 */
+	if (!err && unlikely(d_unhashed(newdentry))) {
+		struct dentry *d;
+
+		d = lookup_one_len(newdentry->d_name.name,
+				   newdentry->d_parent,
+				   newdentry->d_name.len);
+		if (IS_ERR(d)) {
+			err = PTR_ERR(d);
+			pr_warn("overlayfs: failed lookup after mkdir (%pd2, err=%i).\n",
+				newdentry, err);
+			return err;
+		}
+		dput(newdentry);
+		*pnewdentry = d;
+	}
+
+	return err;
+}
+
+int ovl_create_real(struct inode *dir, struct dentry **pnewdentry,
 		    struct cattr *attr, struct dentry *hardlink, bool debug)
 {
+	struct dentry *newdentry = *pnewdentry;
 	int err;
 
 	if (newdentry->d_inode)
@@ -131,7 +163,7 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry,
 			break;
 
 		case S_IFDIR:
-			err = ovl_do_mkdir(dir, newdentry, attr->mode, debug);
+			err = ovl_create_real_dir(dir, pnewdentry, attr->mode);
 			break;
 
 		case S_IFCHR:
@@ -150,7 +182,7 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry,
 			err = -EPERM;
 		}
 	}
-	if (!err && WARN_ON(!newdentry->d_inode)) {
+	if (!err && WARN_ON(!d_inode(*pnewdentry))) {
 		/*
 		 * Not quite sure if non-instantiated dentry is legal or not.
 		 * VFS doesn't seem to care so check and warn here.
@@ -171,7 +203,7 @@ struct dentry *ovl_create_temp(struct dentry *workdir, struct cattr *attr,
 	if (IS_ERR(temp))
 		return temp;
 
-	err = ovl_create_real(wdir, temp, attr, hardlink, true);
+	err = ovl_create_real(wdir, &temp, attr, hardlink, true);
 	if (err) {
 		dput(temp);
 		return ERR_PTR(err);
@@ -261,7 +293,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
 	err = PTR_ERR(newdentry);
 	if (IS_ERR(newdentry))
 		goto out_unlock;
-	err = ovl_create_real(udir, newdentry, attr, hardlink, false);
+	err = ovl_create_real(udir, &newdentry, attr, hardlink, false);
 	if (err)
 		goto out_dput;
 
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 967183175ef5..a84599268d10 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -378,7 +378,7 @@ struct cattr {
 	umode_t mode;
 	const char *link;
 };
-int ovl_create_real(struct inode *dir, struct dentry *newdentry,
+int ovl_create_real(struct inode *dir, struct dentry **pnewdentry,
 		    struct cattr *attr,
 		    struct dentry *hardlink, bool debug);
 struct dentry *ovl_create_temp(struct dentry *workdir, struct cattr *attr,
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 492d534058ae..d83c0543c03c 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -603,7 +603,7 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs,
 			goto retry;
 		}
 
-		err = ovl_create_real(dir, work,
+		err = ovl_create_real(dir, &work,
 				      &(struct cattr){.mode = S_IFDIR | 0},
 				      NULL, true);
 		if (err)
-- 
2.7.4

      parent reply	other threads:[~2018-05-15 10:26 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-15 10:26 [PATCH v3 0/4] Overlayfs mkdir related fixes Amir Goldstein
2018-05-15 10:26 ` [PATCH v3 1/4] ovl: use insert_inode_locked4() to hash a newly created inode Amir Goldstein
2018-05-15 13:23   ` Vivek Goyal
2018-05-15 13:37     ` Amir Goldstein
2018-05-16  8:34       ` Miklos Szeredi
2018-05-16  9:51         ` Amir Goldstein
2018-05-16 10:14           ` Miklos Szeredi
2018-05-16 11:03             ` Amir Goldstein
2018-05-17  6:03       ` Amir Goldstein
2018-05-17  8:10         ` Miklos Szeredi
2018-05-17  8:45           ` Amir Goldstein
2018-05-17  8:53           ` Miklos Szeredi
2018-05-17  8:58             ` Amir Goldstein
2018-05-17  9:07               ` Miklos Szeredi
2018-05-17 16:14                 ` Amir Goldstein
2018-05-15 10:26 ` [PATCH v3 2/4] ovl: relax WARN_ON() real inode attributes mismatch Amir Goldstein
2018-05-15 12:48   ` Vivek Goyal
2018-05-15 12:55     ` Amir Goldstein
2018-05-16 10:29   ` Miklos Szeredi
2018-05-16 11:06     ` Amir Goldstein
2018-05-16 11:18       ` Miklos Szeredi
2018-05-16 13:46         ` Amir Goldstein
2018-05-15 10:26 ` [PATCH v3 3/4] ovl: create helper ovl_create_temp() Amir Goldstein
2018-05-16 10:41   ` Miklos Szeredi
2018-05-16 11:15     ` Amir Goldstein
2018-05-16 11:37       ` Miklos Szeredi
2018-05-15 10:26 ` Amir Goldstein [this message]

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=1526379972-20923-5-git-send-email-amir73il@gmail.com \
    --to=amir73il@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=vgoyal@redhat.com \
    --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.