From dddeb8745c78d3352df3171d69a938107660fb83 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 25 Oct 2021 20:03:33 -0700 Subject: [PATCH] virtio console: Harden multiport against invalid host input It's possible for the host to set the multiport flag, but pass in 0 multiports, which results in: BUG: KASAN: slab-out-of-bounds in init_vqs+0x244/0x6c0 drivers/char/virtio_console.c:1878 Write of size 8 at addr ffff888001cc24a0 by task swapper/1 CPU: 0 PID: 1 Comm: swapper Not tainted 5.15.0-rc1-140273-gaab0bb9fbaa1-dirty #588 Call Trace: __dump_stack lib/dump_stack.c:88 dump_stack_lvl+0x28/0x33 lib/dump_stack.c:106 print_address_description.constprop.0+0x34/0x2c0 mm/kasan/report.c:260 __kasan_report mm/kasan/report.c:446 kasan_report.cold+0xd7/0x1fe mm/kasan/report.c:463 __asan_store8+0xc1/0x170 init_vqs+0x244/0x6c0 drivers/char/virtio_console.c:1878 virtcons_probe+0x1a3/0x5b0 drivers/char/virtio_console.c:2042 virtio_dev_probe+0x2b9/0x500 drivers/virtio/virtio.c:263 call_driver_probe drivers/base/dd.c:515 really_probe+0x1c9/0x5b0 drivers/base/dd.c:601 really_probe_debug drivers/base/dd.c:694 __driver_probe_device+0x10d/0x1f0 drivers/base/dd.c:754 driver_probe_device+0x68/0x150 drivers/base/dd.c:786 __driver_attach+0xca/0x200 drivers/base/dd.c:1145 bus_for_each_dev+0x108/0x190 drivers/base/bus.c:301 driver_attach+0x30/0x40 drivers/base/dd.c:1162 bus_add_driver+0x325/0x3c0 drivers/base/bus.c:618 driver_register+0xf3/0x1d0 drivers/base/driver.c:171 ... Add a suitable sanity check. Signed-off-by: Andi Kleen --- drivers/char/virtio_console.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 9fa3c76a267f50..ac416332277209 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1847,6 +1847,9 @@ static int init_vqs(struct ports_device *portdev) int err; nr_ports = portdev->max_nr_ports; + if (use_multiport(portdev) && nr_ports < 1) + return -EINVAL; + nr_queues = use_multiport(portdev) ? (nr_ports + 1) * 2 : 2; vqs = kmalloc_array(nr_queues, sizeof(struct virtqueue *), GFP_KERNEL);