lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1431367690-5223-90-git-send-email-viro@ZenIV.linux.org.uk>
Date:	Mon, 11 May 2015 19:07:50 +0100
From:	Al Viro <viro@...IV.linux.org.uk>
To:	Linus Torvalds <torvalds@...ux-foundation.org>
Cc:	Neil Brown <neilb@...e.de>, Christoph Hellwig <hch@...radead.org>,
	linux-kernel@...r.kernel.org, linux-fsdevel@...r.kernel.org
Subject: [PATCH v3 090/110] namei: lift terminate_walk() all the way up

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

Lift it from link_path_walk(), trailing_symlink(), lookup_last(),
mountpoint_last(), complete_walk() and do_last().  A _lot_ of
those suckers merge.

Signed-off-by: Al Viro <viro@...iv.linux.org.uk>
---
 fs/namei.c | 106 ++++++++++++++++++++-----------------------------------------
 1 file changed, 34 insertions(+), 72 deletions(-)

diff --git a/fs/namei.c b/fs/namei.c
index 46f4266..27c3859 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -563,8 +563,6 @@ static inline int nd_alloc_stack(struct nameidata *nd)
  * to restart the path walk from the beginning in ref-walk mode.
  */
 
-static void terminate_walk(struct nameidata *nd);
-
 /**
  * unlazy_walk - try to switch to ref-walk mode.
  * @nd: nameidata pathwalk data
@@ -673,10 +671,8 @@ static int complete_walk(struct nameidata *nd)
 	if (nd->flags & LOOKUP_RCU) {
 		if (!(nd->flags & LOOKUP_ROOT))
 			nd->root.mnt = NULL;
-		if (unlikely(unlazy_walk(nd, NULL))) {
-			terminate_walk(nd);
+		if (unlikely(unlazy_walk(nd, NULL)))
 			return -ECHILD;
-		}
 	}
 
 	if (likely(!(nd->flags & LOOKUP_JUMPED)))
@@ -692,7 +688,6 @@ static int complete_walk(struct nameidata *nd)
 	if (!status)
 		status = -ESTALE;
 
-	terminate_walk(nd);
 	return status;
 }
 
@@ -1858,7 +1853,6 @@ OK:
 			break;
 		}
 	}
-	terminate_walk(nd);
 	return err;
 }
 
@@ -1974,38 +1968,26 @@ static const char *trailing_symlink(struct nameidata *nd)
 {
 	const char *s;
 	int error = may_follow_link(nd);
-	if (unlikely(error)) {
-		terminate_walk(nd);
+	if (unlikely(error))
 		return ERR_PTR(error);
-	}
 	nd->flags |= LOOKUP_PARENT;
 	nd->stack[0].name = NULL;
 	s = get_link(nd);
-	if (unlikely(IS_ERR(s))) {
-		terminate_walk(nd);
-		return s;
-	}
-	if (unlikely(!s))
-		s = "";
-	return s;
+	return s ? s : "";
 }
 
 static inline int lookup_last(struct nameidata *nd)
 {
-	int err;
 	if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len])
 		nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
 
 	nd->flags &= ~LOOKUP_PARENT;
-	err = walk_component(nd,
+	return walk_component(nd,
 			nd->flags & LOOKUP_FOLLOW
 				? nd->depth
 					? WALK_PUT | WALK_GET
 					: WALK_GET
 				: 0);
-	if (err < 0)
-		terminate_walk(nd);
-	return err;
 }
 
 /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
@@ -2025,16 +2007,14 @@ static int path_lookupat(int dfd, const struct filename *name,
 			break;
 		}
 	}
-
 	if (!err)
 		err = complete_walk(nd);
 
-	if (!err && nd->flags & LOOKUP_DIRECTORY) {
-		if (!d_can_lookup(nd->path.dentry)) {
-			path_put(&nd->path);
+	if (!err && nd->flags & LOOKUP_DIRECTORY)
+		if (!d_can_lookup(nd->path.dentry))
 			err = -ENOTDIR;
-		}
-	}
+	if (err)
+		terminate_walk(nd);
 
 	path_cleanup(nd);
 	return err;
@@ -2069,6 +2049,8 @@ static int path_parentat(int dfd, const struct filename *name,
 	err = link_path_walk(s, nd);
 	if (!err)
 		err = complete_walk(nd);
+	if (err)
+		terminate_walk(nd);
 	path_cleanup(nd);
 	return err;
 }
@@ -2320,10 +2302,8 @@ mountpoint_last(struct nameidata *nd, struct path *path)
 
 	/* If we're in rcuwalk, drop out of it to handle last component */
 	if (nd->flags & LOOKUP_RCU) {
-		if (unlazy_walk(nd, NULL)) {
-			error = -ECHILD;
-			goto out;
-		}
+		if (unlazy_walk(nd, NULL))
+			return -ECHILD;
 	}
 
 	nd->flags &= ~LOOKUP_PARENT;
@@ -2331,7 +2311,7 @@ mountpoint_last(struct nameidata *nd, struct path *path)
 	if (unlikely(nd->last_type != LAST_NORM)) {
 		error = handle_dots(nd, nd->last_type);
 		if (error)
-			goto out;
+			return error;
 		dentry = dget(nd->path.dentry);
 		goto done;
 	}
@@ -2346,41 +2326,32 @@ mountpoint_last(struct nameidata *nd, struct path *path)
 		 */
 		dentry = d_alloc(dir, &nd->last);
 		if (!dentry) {
-			error = -ENOMEM;
 			mutex_unlock(&dir->d_inode->i_mutex);
-			goto out;
+			return -ENOMEM;
 		}
 		dentry = lookup_real(dir->d_inode, dentry, nd->flags);
-		error = PTR_ERR(dentry);
 		if (IS_ERR(dentry)) {
 			mutex_unlock(&dir->d_inode->i_mutex);
-			goto out;
+			return PTR_ERR(dentry);
 		}
 	}
 	mutex_unlock(&dir->d_inode->i_mutex);
 
 done:
 	if (d_is_negative(dentry)) {
-		error = -ENOENT;
 		dput(dentry);
-		goto out;
+		return -ENOENT;
 	}
 	if (nd->depth)
 		put_link(nd);
 	path->dentry = dentry;
 	path->mnt = nd->path.mnt;
 	error = should_follow_link(nd, path, nd->flags & LOOKUP_FOLLOW);
-	if (unlikely(error)) {
-		if (error < 0)
-			goto out;
+	if (unlikely(error))
 		return error;
-	}
 	mntget(path->mnt);
 	follow_mount(path);
-	error = 0;
-out:
-	terminate_walk(nd);
-	return error;
+	return 0;
 }
 
 /**
@@ -2409,6 +2380,7 @@ path_mountpoint(int dfd, const struct filename *name, struct path *path,
 			break;
 		}
 	}
+	terminate_walk(nd);
 	path_cleanup(nd);
 	return err;
 }
@@ -2982,10 +2954,8 @@ static int do_last(struct nameidata *nd,
 
 	if (nd->last_type != LAST_NORM) {
 		error = handle_dots(nd, nd->last_type);
-		if (unlikely(error)) {
-			terminate_walk(nd);
+		if (unlikely(error))
 			return error;
-		}
 		goto finish_open;
 	}
 
@@ -2998,7 +2968,7 @@ static int do_last(struct nameidata *nd,
 			goto finish_lookup;
 
 		if (error < 0)
-			goto out;
+			return error;
 
 		BUG_ON(nd->inode != dir->d_inode);
 	} else {
@@ -3013,10 +2983,9 @@ static int do_last(struct nameidata *nd,
 			return error;
 
 		audit_inode(name, dir, LOOKUP_PARENT);
-		error = -EISDIR;
 		/* trailing slashes? */
-		if (nd->last.name[nd->last.len])
-			goto out;
+		if (unlikely(nd->last.name[nd->last.len]))
+			return -EISDIR;
 	}
 
 retry_lookup:
@@ -3071,35 +3040,31 @@ retry_lookup:
 		got_write = false;
 	}
 
-	error = -EEXIST;
-	if ((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))
-		goto exit_dput;
+	if (unlikely((open_flag & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT))) {
+		path_to_nameidata(&path, nd);
+		return -EEXIST;
+	}
 
 	error = follow_managed(&path, nd);
-	if (error < 0)
-		goto out;
+	if (unlikely(error < 0))
+		return error;
 
 	BUG_ON(nd->flags & LOOKUP_RCU);
 	inode = path.dentry->d_inode;
-	error = -ENOENT;
-	if (d_is_negative(path.dentry)) {
+	if (unlikely(d_is_negative(path.dentry))) {
 		path_to_nameidata(&path, nd);
-		goto out;
+		return -ENOENT;
 	}
 finish_lookup:
 	if (nd->depth)
 		put_link(nd);
 	error = should_follow_link(nd, &path, nd->flags & LOOKUP_FOLLOW);
-	if (unlikely(error)) {
-		if (error < 0)
-			goto out;
+	if (unlikely(error))
 		return error;
-	}
 
 	if (unlikely(d_is_symlink(path.dentry)) && !(open_flag & O_PATH)) {
 		path_to_nameidata(&path, nd);
-		error = -ELOOP;
-		goto out;
+		return -ELOOP;
 	}
 
 	if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path.mnt) {
@@ -3165,12 +3130,8 @@ out:
 	if (got_write)
 		mnt_drop_write(nd->path.mnt);
 	path_put(&save_parent);
-	terminate_walk(nd);
 	return error;
 
-exit_dput:
-	path_put_conditional(&path, nd);
-	goto out;
 exit_fput:
 	fput(file);
 	goto out;
@@ -3289,6 +3250,7 @@ static struct file *path_openat(int dfd, struct filename *pathname,
 			break;
 		}
 	}
+	terminate_walk(nd);
 	path_cleanup(nd);
 out2:
 	if (!(opened & FILE_OPENED)) {
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ