The device_block_size read from the virtio-mem config space is used as a
divisor and also in ALIGN_DOWN() further down the code path in the
driver without further validation. A zero value leads to a division by
zero, and a non-power-of-two value corrupts the ALIGN_DOWN() bitmask
arithmetic leading to a misreporting of guest-usable ram, post crash.

Reject both at init time instead of trusting the device.

Signed-off-by: Hari Mishal <[email protected]>
---
v2: dropped the redundant explicit zero check, since
    is_power_of_2(0) already returns false.

 drivers/virtio/virtio_mem.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/virtio/virtio_mem.c b/drivers/virtio/virtio_mem.c
index 11c441501582..0e04fec458af 100644
--- a/drivers/virtio/virtio_mem.c
+++ b/drivers/virtio/virtio_mem.c
@@ -2847,6 +2847,12 @@ static int virtio_mem_init(struct virtio_mem *vm)
                        &vm->plugged_size);
        virtio_cread_le(vm->vdev, struct virtio_mem_config, block_size,
                        &vm->device_block_size);
+       if (!is_power_of_2(vm->device_block_size)) {
+               dev_err(&vm->vdev->dev,
+                       "invalid device block size: 0x%llx\n",
+                       (unsigned long long)vm->device_block_size);
+               return -EINVAL;
+       }
        virtio_cread_le(vm->vdev, struct virtio_mem_config, node_id,
                        &node_id);
        vm->nid = virtio_mem_translate_node_id(vm, node_id);
-- 
2.43.0


Reply via email to