Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95c607d9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull vfs fixes from Al Viro:
 "A couple of fixes for bugs caught while digging in fs/namei.c.  The
  first one is this cycle regression, the second is 3.11 and later"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  path_openat(): fix double fput()
  namei: d_is_negative() should be checked before ->d_seq validation
parents af647288 f15133df
Loading
Loading
Loading
Loading
+15 −7
Original line number Original line Diff line number Diff line
@@ -1415,6 +1415,7 @@ static int lookup_fast(struct nameidata *nd,
	 */
	 */
	if (nd->flags & LOOKUP_RCU) {
	if (nd->flags & LOOKUP_RCU) {
		unsigned seq;
		unsigned seq;
		bool negative;
		dentry = __d_lookup_rcu(parent, &nd->last, &seq);
		dentry = __d_lookup_rcu(parent, &nd->last, &seq);
		if (!dentry)
		if (!dentry)
			goto unlazy;
			goto unlazy;
@@ -1424,8 +1425,11 @@ static int lookup_fast(struct nameidata *nd,
		 * the dentry name information from lookup.
		 * the dentry name information from lookup.
		 */
		 */
		*inode = dentry->d_inode;
		*inode = dentry->d_inode;
		negative = d_is_negative(dentry);
		if (read_seqcount_retry(&dentry->d_seq, seq))
		if (read_seqcount_retry(&dentry->d_seq, seq))
			return -ECHILD;
			return -ECHILD;
		if (negative)
			return -ENOENT;


		/*
		/*
		 * This sequence count validates that the parent had no
		 * This sequence count validates that the parent had no
@@ -1472,6 +1476,10 @@ static int lookup_fast(struct nameidata *nd,
		goto need_lookup;
		goto need_lookup;
	}
	}


	if (unlikely(d_is_negative(dentry))) {
		dput(dentry);
		return -ENOENT;
	}
	path->mnt = mnt;
	path->mnt = mnt;
	path->dentry = dentry;
	path->dentry = dentry;
	err = follow_managed(path, nd->flags);
	err = follow_managed(path, nd->flags);
@@ -1583,10 +1591,10 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
			goto out_err;
			goto out_err;


		inode = path->dentry->d_inode;
		inode = path->dentry->d_inode;
	}
		err = -ENOENT;
		err = -ENOENT;
		if (d_is_negative(path->dentry))
		if (d_is_negative(path->dentry))
			goto out_path_put;
			goto out_path_put;
	}


	if (should_follow_link(path->dentry, follow)) {
	if (should_follow_link(path->dentry, follow)) {
		if (nd->flags & LOOKUP_RCU) {
		if (nd->flags & LOOKUP_RCU) {
@@ -3036,14 +3044,13 @@ static int do_last(struct nameidata *nd, struct path *path,


	BUG_ON(nd->flags & LOOKUP_RCU);
	BUG_ON(nd->flags & LOOKUP_RCU);
	inode = path->dentry->d_inode;
	inode = path->dentry->d_inode;
finish_lookup:
	/* we _can_ be in RCU mode here */
	error = -ENOENT;
	error = -ENOENT;
	if (d_is_negative(path->dentry)) {
	if (d_is_negative(path->dentry)) {
		path_to_nameidata(path, nd);
		path_to_nameidata(path, nd);
		goto out;
		goto out;
	}
	}

finish_lookup:
	/* we _can_ be in RCU mode here */
	if (should_follow_link(path->dentry, !symlink_ok)) {
	if (should_follow_link(path->dentry, !symlink_ok)) {
		if (nd->flags & LOOKUP_RCU) {
		if (nd->flags & LOOKUP_RCU) {
			if (unlikely(nd->path.mnt != path->mnt ||
			if (unlikely(nd->path.mnt != path->mnt ||
@@ -3226,7 +3233,7 @@ static struct file *path_openat(int dfd, struct filename *pathname,


	if (unlikely(file->f_flags & __O_TMPFILE)) {
	if (unlikely(file->f_flags & __O_TMPFILE)) {
		error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened);
		error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened);
		goto out;
		goto out2;
	}
	}


	error = path_init(dfd, pathname, flags, nd);
	error = path_init(dfd, pathname, flags, nd);
@@ -3256,6 +3263,7 @@ static struct file *path_openat(int dfd, struct filename *pathname,
	}
	}
out:
out:
	path_cleanup(nd);
	path_cleanup(nd);
out2:
	if (!(opened & FILE_OPENED)) {
	if (!(opened & FILE_OPENED)) {
		BUG_ON(!error);
		BUG_ON(!error);
		put_filp(file);
		put_filp(file);