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
This commit is contained in:
@@ -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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
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);
|
||||||
|
4
fs/aio.c
4
fs/aio.c
@@ -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;
|
||||||
|
13
fs/dcache.c
13
fs/dcache.c
@@ -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,
|
|||||||
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 @@ restart:
|
|||||||
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
|
|||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user