[fuse] fix race between checking and setting file->private_data
BKL does not protect against races if the task may sleep between checking and setting a value. So move checking of file->private_data near to setting it in fuse_fill_super(). Found by Al Viro. Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
This commit is contained in:
parent
6dbbcb1205
commit
8aa09a50b5
1 changed files with 8 additions and 5 deletions
|
@ -500,11 +500,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
|
|||
if (file->f_op != &fuse_dev_operations)
|
||||
return -EINVAL;
|
||||
|
||||
/* Setting file->private_data can't race with other mount()
|
||||
instances, since BKL is held for ->get_sb() */
|
||||
if (file->private_data)
|
||||
return -EINVAL;
|
||||
|
||||
fc = new_conn();
|
||||
if (!fc)
|
||||
return -ENOMEM;
|
||||
|
@ -540,6 +535,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
|
|||
if (err)
|
||||
goto err_free_req;
|
||||
|
||||
/* Setting file->private_data can't race with other mount()
|
||||
instances, since BKL is held for ->get_sb() */
|
||||
err = -EINVAL;
|
||||
if (file->private_data)
|
||||
goto err_kobject_del;
|
||||
|
||||
sb->s_root = root_dentry;
|
||||
fc->mounted = 1;
|
||||
fc->connected = 1;
|
||||
|
@ -556,6 +557,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
|
|||
|
||||
return 0;
|
||||
|
||||
err_kobject_del:
|
||||
kobject_del(&fc->kobj);
|
||||
err_free_req:
|
||||
fuse_request_free(init_req);
|
||||
err_put_root:
|
||||
|
|
Loading…
Reference in a new issue