Эх сурвалжийг харах

[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>
Miklos Szeredi 19 жил өмнө
parent
commit
8aa09a50b5
1 өөрчлөгдсөн 8 нэмэгдсэн , 5 устгасан
  1. 8 5
      fs/fuse/inode.c

+ 8 - 5
fs/fuse/inode.c

@@ -500,11 +500,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
 	if (file->f_op != &fuse_dev_operations)
 	if (file->f_op != &fuse_dev_operations)
 		return -EINVAL;
 		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();
 	fc = new_conn();
 	if (!fc)
 	if (!fc)
 		return -ENOMEM;
 		return -ENOMEM;
@@ -540,6 +535,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
 	if (err)
 	if (err)
 		goto err_free_req;
 		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;
 	sb->s_root = root_dentry;
 	fc->mounted = 1;
 	fc->mounted = 1;
 	fc->connected = 1;
 	fc->connected = 1;
@@ -556,6 +557,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
 
 
 	return 0;
 	return 0;
 
 
+ err_kobject_del:
+	kobject_del(&fc->kobj);
  err_free_req:
  err_free_req:
 	fuse_request_free(init_req);
 	fuse_request_free(init_req);
  err_put_root:
  err_put_root: