diff options
| author | Miklos Szeredi <miklos@szeredi.hu> | 2006-04-26 04:49:16 -0400 |
|---|---|---|
| committer | Miklos Szeredi <miklos@szeredi.hu> | 2006-04-26 04:49:16 -0400 |
| commit | 8aa09a50b5d9dbdf627f79e19d72d82994348089 (patch) | |
| tree | 5b50a1b62c8b95223023053595c452b0641f5767 | |
| parent | 6dbbcb120570d747b00783820ee02d1e1bcf63de (diff) | |
[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>
| -rw-r--r-- | fs/fuse/inode.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index fd34037b0588..7627022446b2 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
| @@ -500,11 +500,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
| 500 | if (file->f_op != &fuse_dev_operations) | 500 | if (file->f_op != &fuse_dev_operations) |
| 501 | return -EINVAL; | 501 | return -EINVAL; |
| 502 | 502 | ||
| 503 | /* Setting file->private_data can't race with other mount() | ||
| 504 | instances, since BKL is held for ->get_sb() */ | ||
| 505 | if (file->private_data) | ||
| 506 | return -EINVAL; | ||
| 507 | |||
| 508 | fc = new_conn(); | 503 | fc = new_conn(); |
| 509 | if (!fc) | 504 | if (!fc) |
| 510 | return -ENOMEM; | 505 | return -ENOMEM; |
| @@ -540,6 +535,12 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
| 540 | if (err) | 535 | if (err) |
| 541 | goto err_free_req; | 536 | goto err_free_req; |
| 542 | 537 | ||
| 538 | /* Setting file->private_data can't race with other mount() | ||
| 539 | instances, since BKL is held for ->get_sb() */ | ||
| 540 | err = -EINVAL; | ||
| 541 | if (file->private_data) | ||
| 542 | goto err_kobject_del; | ||
| 543 | |||
| 543 | sb->s_root = root_dentry; | 544 | sb->s_root = root_dentry; |
| 544 | fc->mounted = 1; | 545 | fc->mounted = 1; |
| 545 | fc->connected = 1; | 546 | fc->connected = 1; |
| @@ -556,6 +557,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
| 556 | 557 | ||
| 557 | return 0; | 558 | return 0; |
| 558 | 559 | ||
| 560 | err_kobject_del: | ||
| 561 | kobject_del(&fc->kobj); | ||
| 559 | err_free_req: | 562 | err_free_req: |
| 560 | fuse_request_free(init_req); | 563 | fuse_request_free(init_req); |
| 561 | err_put_root: | 564 | err_put_root: |
