Commit 2821fe6b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

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
...@@ -456,13 +456,13 @@ static int remove_file(struct dentry *parent, char *name) ...@@ -456,13 +456,13 @@ static int remove_file(struct dentry *parent, char *name)
spin_lock(&tmp->d_lock); spin_lock(&tmp->d_lock);
if (!(d_unhashed(tmp) && tmp->d_inode)) { if (!(d_unhashed(tmp) && tmp->d_inode)) {
dget_dlock(tmp);
__d_drop(tmp); __d_drop(tmp);
spin_unlock(&tmp->d_lock); spin_unlock(&tmp->d_lock);
simple_unlink(parent->d_inode, tmp); simple_unlink(parent->d_inode, tmp);
} else { } else {
spin_unlock(&tmp->d_lock); spin_unlock(&tmp->d_lock);
} }
dput(tmp);
ret = 0; ret = 0;
bail: bail:
...@@ -491,6 +491,7 @@ static int remove_device_files(struct super_block *sb, ...@@ -491,6 +491,7 @@ static int remove_device_files(struct super_block *sb,
goto bail; goto bail;
} }
mutex_lock(&dir->d_inode->i_mutex);
remove_file(dir, "counters"); remove_file(dir, "counters");
remove_file(dir, "counter_names"); remove_file(dir, "counter_names");
remove_file(dir, "portcounter_names"); remove_file(dir, "portcounter_names");
...@@ -505,8 +506,10 @@ static int remove_device_files(struct super_block *sb, ...@@ -505,8 +506,10 @@ static int remove_device_files(struct super_block *sb,
} }
} }
remove_file(dir, "flash"); remove_file(dir, "flash");
d_delete(dir); mutex_unlock(&dir->d_inode->i_mutex);
ret = simple_rmdir(root->d_inode, dir); ret = simple_rmdir(root->d_inode, dir);
d_delete(dir);
dput(dir);
bail: bail:
mutex_unlock(&root->d_inode->i_mutex); mutex_unlock(&root->d_inode->i_mutex);
......
...@@ -163,8 +163,8 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages) ...@@ -163,8 +163,8 @@ static struct file *aio_private_file(struct kioctx *ctx, loff_t nr_pages)
struct file *file; struct file *file;
struct path path; struct path path;
struct inode *inode = alloc_anon_inode(aio_mnt->mnt_sb); struct inode *inode = alloc_anon_inode(aio_mnt->mnt_sb);
if (!inode) if (IS_ERR(inode))
return ERR_PTR(-ENOMEM); return ERR_CAST(inode);
inode->i_mapping->a_ops = &aio_ctx_aops; inode->i_mapping->a_ops = &aio_ctx_aops;
inode->i_mapping->private_data = ctx; inode->i_mapping->private_data = ctx;
......
...@@ -2912,9 +2912,9 @@ static int prepend_path(const struct path *path, ...@@ -2912,9 +2912,9 @@ static int prepend_path(const struct path *path,
const struct path *root, const struct path *root,
char **buffer, int *buflen) char **buffer, int *buflen)
{ {
struct dentry *dentry = path->dentry; struct dentry *dentry;
struct vfsmount *vfsmnt = path->mnt; struct vfsmount *vfsmnt;
struct mount *mnt = real_mount(vfsmnt); struct mount *mnt;
int error = 0; int error = 0;
unsigned seq, m_seq = 0; unsigned seq, m_seq = 0;
char *bptr; char *bptr;
...@@ -2924,10 +2924,14 @@ static int prepend_path(const struct path *path, ...@@ -2924,10 +2924,14 @@ static int prepend_path(const struct path *path,
restart_mnt: restart_mnt:
read_seqbegin_or_lock(&mount_lock, &m_seq); read_seqbegin_or_lock(&mount_lock, &m_seq);
seq = 0; seq = 0;
rcu_read_lock();
restart: restart:
bptr = *buffer; bptr = *buffer;
blen = *buflen; blen = *buflen;
error = 0; error = 0;
dentry = path->dentry;
vfsmnt = path->mnt;
mnt = real_mount(vfsmnt);
read_seqbegin_or_lock(&rename_lock, &seq); read_seqbegin_or_lock(&rename_lock, &seq);
while (dentry != root->dentry || vfsmnt != root->mnt) { while (dentry != root->dentry || vfsmnt != root->mnt) {
struct dentry * parent; struct dentry * parent;
...@@ -2971,6 +2975,9 @@ static int prepend_path(const struct path *path, ...@@ -2971,6 +2975,9 @@ static int prepend_path(const struct path *path,
goto restart; goto restart;
} }
done_seqretry(&rename_lock, seq); done_seqretry(&rename_lock, seq);
if (!(m_seq & 1))
rcu_read_unlock();
if (need_seqretry(&mount_lock, m_seq)) { if (need_seqretry(&mount_lock, m_seq)) {
m_seq = 1; m_seq = 1;
goto restart_mnt; goto restart_mnt;
......
...@@ -1494,6 +1494,7 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp ...@@ -1494,6 +1494,7 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp
if (is_deleg && arg == F_WRLCK) { if (is_deleg && arg == F_WRLCK) {
/* Write delegations are not currently supported: */ /* Write delegations are not currently supported: */
mutex_unlock(&inode->i_mutex);
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
return -EINVAL; return -EINVAL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment