X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=fs%2Fsuper.c;h=4d486caa29a8e562223b173b807cab28cf8a04b6;hb=HEAD;hp=adb0c0de428c2c88c0322ae739cbe108f01ae085;hpb=fbd78afe34d9cc3a86aff7cc214d9f06e815e63e;p=mirror_ubuntu-artful-kernel.git diff --git a/fs/super.c b/fs/super.c index adb0c0de428c..4d486caa29a8 100644 --- a/fs/super.c +++ b/fs/super.c @@ -168,7 +168,6 @@ static void destroy_super(struct super_block *s) WARN_ON(!list_empty(&s->s_mounts)); put_user_ns(s->s_user_ns); kfree(s->s_subtype); - kfree(s->s_options); call_rcu(&s->rcu, destroy_super_rcu); } @@ -508,7 +507,7 @@ retry: return ERR_PTR(-ENOMEM); goto retry; } - + err = set(s, data); if (err) { spin_unlock(&sb_lock); @@ -771,7 +770,7 @@ restart: spin_unlock(&sb_lock); return NULL; } - + struct super_block *user_get_super(dev_t dev) { struct super_block *sb; @@ -1079,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 @@ -1088,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); @@ -1100,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; } /* @@ -1131,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: @@ -1147,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); }