Skip to content

Commit 82e89ea

Browse files
YongjiXiemstsirkin
authored andcommitted
virtio-blk: Add validation for block size in config space
An untrusted device might presents an invalid block size in configuration space. This tries to add validation for it in the validate callback and clear the VIRTIO_BLK_F_BLK_SIZE feature bit if the value is out of the supported range. And we also double check the value in virtblk_probe() in case that it's changed after the validation. Signed-off-by: Xie Yongji <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Michael S. Tsirkin <[email protected]> Acked-by: Jason Wang <[email protected]>
1 parent e74cfa9 commit 82e89ea

File tree

1 file changed

+33
-6
lines changed

1 file changed

+33
-6
lines changed

drivers/block/virtio_blk.c

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,28 @@ static const struct blk_mq_ops virtio_mq_ops = {
692692
static unsigned int virtblk_queue_depth;
693693
module_param_named(queue_depth, virtblk_queue_depth, uint, 0444);
694694

695+
static int virtblk_validate(struct virtio_device *vdev)
696+
{
697+
u32 blk_size;
698+
699+
if (!vdev->config->get) {
700+
dev_err(&vdev->dev, "%s failure: config access disabled\n",
701+
__func__);
702+
return -EINVAL;
703+
}
704+
705+
if (!virtio_has_feature(vdev, VIRTIO_BLK_F_BLK_SIZE))
706+
return 0;
707+
708+
blk_size = virtio_cread32(vdev,
709+
offsetof(struct virtio_blk_config, blk_size));
710+
711+
if (blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE)
712+
__virtio_clear_bit(vdev, VIRTIO_BLK_F_BLK_SIZE);
713+
714+
return 0;
715+
}
716+
695717
static int virtblk_probe(struct virtio_device *vdev)
696718
{
697719
struct virtio_blk *vblk;
@@ -703,12 +725,6 @@ static int virtblk_probe(struct virtio_device *vdev)
703725
u8 physical_block_exp, alignment_offset;
704726
unsigned int queue_depth;
705727

706-
if (!vdev->config->get) {
707-
dev_err(&vdev->dev, "%s failure: config access disabled\n",
708-
__func__);
709-
return -EINVAL;
710-
}
711-
712728
err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS),
713729
GFP_KERNEL);
714730
if (err < 0)
@@ -823,6 +839,14 @@ static int virtblk_probe(struct virtio_device *vdev)
823839
else
824840
blk_size = queue_logical_block_size(q);
825841

842+
if (unlikely(blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE)) {
843+
dev_err(&vdev->dev,
844+
"block size is changed unexpectedly, now is %u\n",
845+
blk_size);
846+
err = -EINVAL;
847+
goto err_cleanup_disk;
848+
}
849+
826850
/* Use topology information if available */
827851
err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
828852
struct virtio_blk_config, physical_block_exp,
@@ -881,6 +905,8 @@ static int virtblk_probe(struct virtio_device *vdev)
881905
device_add_disk(&vdev->dev, vblk->disk, virtblk_attr_groups);
882906
return 0;
883907

908+
err_cleanup_disk:
909+
blk_cleanup_disk(vblk->disk);
884910
out_free_tags:
885911
blk_mq_free_tag_set(&vblk->tag_set);
886912
out_free_vq:
@@ -983,6 +1009,7 @@ static struct virtio_driver virtio_blk = {
9831009
.driver.name = KBUILD_MODNAME,
9841010
.driver.owner = THIS_MODULE,
9851011
.id_table = id_table,
1012+
.validate = virtblk_validate,
9861013
.probe = virtblk_probe,
9871014
.remove = virtblk_remove,
9881015
.config_changed = virtblk_config_changed,

0 commit comments

Comments
 (0)