[PATCH V2 04/12] virtio_console: validate max_nr_ports before trying to use it

Jason Wang
2021-10-12T06:53:28Z

We calculate nr_ports based on the max_nr_ports:

nr_queues = use_multiport(portdev) ? (nr_ports + 1) * 2 : 2;

If the device advertises a large max_nr_ports, we will end up with a
integer overflow. Fixing this by validating the max_nr_ports
advertised by the device in .validate() and clear the MULTIPORT is
it's greater than 0x8000 (which is guaranteed be safe).

Cc: Amit Shah <amit@kernel.org>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/char/virtio_console.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index daeed31df622..ef13763699c0 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -28,6 +28,7 @@
#include "../tty/hvc/hvc_console.h"

#define is_rproc_enabled IS_ENABLED(CONFIG_REMOTEPROC)
+#define VIRTCONS_MAX_PORTS 0x8000

/*
* This is a global struct for storing common data for all the devices
@@ -1981,6 +1982,8 @@ static void virtcons_remove(struct virtio_device *vdev)

static int virtcons_validate(struct virtio_device *vdev)
{
+ u32 max_nr_ports;
+
if (is_rproc_serial(vdev)) {
/* Don't test F_SIZE at all if we're rproc: not a
* valid feature! */
@@ -1999,6 +2002,13 @@ static int virtcons_validate(struct virtio_device *vdev)
return -EINVAL;
}

+ if (virtio_cread_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
+ struct virtio_console_config, max_nr_ports,
+ &max_nr_ports) == 0) {
+ if (max_nr_ports == 0 || max_nr_ports > VIRTCONS_MAX_PORTS)
+ __virtio_clear_bit(vdev, VIRTIO_CONSOLE_F_MULTIPORT);
+ }
+
return 0;
}

--
2.25.1