X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=fs%2Fsuper.c;h=4d486caa29a8e562223b173b807cab28cf8a04b6;hb=HEAD;hp=6bc3352adcf39fc5ed6cad77b5df5c9d7db3f9cc;hpb=7e5fed09ddbb7d0f16af0ebdaca2c22b0a2fed77;p=mirror_ubuntu-artful-kernel.git diff --git a/fs/super.c b/fs/super.c index 6bc3352adcf3..4d486caa29a8 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1078,6 +1078,23 @@ struct dentry *mount_bdev(struct file_system_type *fs_type, if (IS_ERR(bdev)) return ERR_CAST(bdev); + if (current_user_ns() != &init_user_ns) { + /* + * For userns mounts, disallow mounting if bdev is open for + * writing + */ + if (!atomic_dec_unless_positive(&bdev->bd_inode->i_writecount)) { + error = -EBUSY; + goto error_bdev; + } + if (bdev->bd_contains != bdev && + !atomic_dec_unless_positive(&bdev->bd_contains->bd_inode->i_writecount)) { + atomic_inc(&bdev->bd_inode->i_writecount); + error = -EBUSY; + goto error_bdev; + } + } + /* * once the super is inserted into the list by sget, s_umount * will protect the lockfs code from trying to start a snapshot @@ -1087,7 +1104,7 @@ struct dentry *mount_bdev(struct file_system_type *fs_type, if (bdev->bd_fsfreeze_count > 0) { mutex_unlock(&bdev->bd_fsfreeze_mutex); error = -EBUSY; - goto error_bdev; + goto error_inc; } s = sget(fs_type, test_bdev_super, set_bdev_super, flags | MS_NOSEC, bdev); @@ -1099,7 +1116,7 @@ struct dentry *mount_bdev(struct file_system_type *fs_type, if ((flags ^ s->s_flags) & MS_RDONLY) { deactivate_locked_super(s); error = -EBUSY; - goto error_bdev; + goto error_inc; } /* @@ -1130,6 +1147,12 @@ struct dentry *mount_bdev(struct file_system_type *fs_type, error_s: error = PTR_ERR(s); +error_inc: + if (current_user_ns() != &init_user_ns) { + atomic_inc(&bdev->bd_inode->i_writecount); + if (bdev->bd_contains != bdev) + atomic_inc(&bdev->bd_contains->bd_inode->i_writecount); + } error_bdev: blkdev_put(bdev, mode); error: @@ -1146,6 +1169,11 @@ void kill_block_super(struct super_block *sb) generic_shutdown_super(sb); sync_blockdev(bdev); WARN_ON_ONCE(!(mode & FMODE_EXCL)); + if (sb->s_user_ns != &init_user_ns) { + atomic_inc(&bdev->bd_inode->i_writecount); + if (bdev->bd_contains != bdev) + atomic_inc(&bdev->bd_contains->bd_inode->i_writecount); + } blkdev_put(bdev, mode | FMODE_EXCL); }