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

Commit 2821fe6b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull VFS fixes from Al Viro:
 "Several fixes, mostly for regressions in the last pile.  Howeover,
  prepend_path() forgetting to reininitalize dentry/vfsmount is in 3.12
  as well and qib_fs had been leaking all along..."

The unpaired RCU lock issue was also independently reported by Dave
Jones with his fuzzer tool..

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  qib_fs: fix (some) dcache abuses
  prepend_path() needs to reinitialize dentry/vfsmount/mnt on restarts
  fix unpaired rcu lock in prepend_path()
  locks: missing unlock on error in generic_add_lease()
  aio: checking for NULL instead of IS_ERR
parents f47671e2 441a9d0e
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -456,13 +456,13 @@ static int remove_file(struct dentry *parent, char *name)

	spin_lock(&tmp->d_lock);
	if (!(d_unhashed(tmp) && tmp->d_inode)) {
		dget_dlock(tmp);
		__d_drop(tmp);
		spin_unlock(&tmp->d_lock);
		simple_unlink(parent->d_inode, tmp);
	} else {
		spin_unlock(&tmp->d_lock);
	}
	dput(tmp);

	ret = 0;
bail:
@@ -491,6 +491,7 @@ static int remove_device_files(struct super_block *sb,
		goto bail;
	}

	mutex_lock(&dir->d_inode->i_mutex);
	remove_file(dir, "counters");
	remove_file(dir, "counter_names");
	remove_file(dir, "portcounter_names");
@@ -505,8 +506,10 @@ static int remove_device_files(struct super_block *sb,
		}
	}
	remove_file(dir, "flash");
	d_delete(dir);
	mutex_unlock(&dir->d_inode->i_mutex);
	ret = simple_rmdir(root->d_inode, dir);
	d_delete(dir);
	dput(dir);

bail:
	mutex_unlock(&root->d_inode->i_mutex);
+2 −2
Original line number Diff line number Diff line
@@ -163,8 +163,8 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
	struct file *file;
	struct path path;
	struct inode *inode = alloc_anon_inode(aio_mnt->mnt_sb);
	if (!inode)
		return ERR_PTR(-ENOMEM);
	if (IS_ERR(inode))
		return ERR_CAST(inode);

	inode->i_mapping->a_ops = &aio_ctx_aops;
	inode->i_mapping->private_data = ctx;
+10 −3
Original line number Diff line number Diff line
@@ -2912,9 +2912,9 @@ static int prepend_path(const struct path *path,
			const struct path *root,
			char **buffer, int *buflen)
{
	struct dentry *dentry = path->dentry;
	struct vfsmount *vfsmnt = path->mnt;
	struct mount *mnt = real_mount(vfsmnt);
	struct dentry *dentry;
	struct vfsmount *vfsmnt;
	struct mount *mnt;
	int error = 0;
	unsigned seq, m_seq = 0;
	char *bptr;
@@ -2924,10 +2924,14 @@ static int prepend_path(const struct path *path,
restart_mnt:
	read_seqbegin_or_lock(&mount_lock, &m_seq);
	seq = 0;
	rcu_read_lock();
restart:
	bptr = *buffer;
	blen = *buflen;
	error = 0;
	dentry = path->dentry;
	vfsmnt = path->mnt;
	mnt = real_mount(vfsmnt);
	read_seqbegin_or_lock(&rename_lock, &seq);
	while (dentry != root->dentry || vfsmnt != root->mnt) {
		struct dentry * parent;
@@ -2971,6 +2975,9 @@ static int prepend_path(const struct path *path,
		goto restart;
	}
	done_seqretry(&rename_lock, seq);

	if (!(m_seq & 1))
		rcu_read_unlock();
	if (need_seqretry(&mount_lock, m_seq)) {
		m_seq = 1;
		goto restart_mnt;
+1 −0
Original line number Diff line number Diff line
@@ -1494,6 +1494,7 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp

	if (is_deleg && arg == F_WRLCK) {
		/* Write delegations are not currently supported: */
		mutex_unlock(&inode->i_mutex);
		WARN_ON_ONCE(1);
		return -EINVAL;
	}