summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2024-09-16 21:16:44 +0300
committerMichael S. Tsirkin <mst@redhat.com>2024-09-25 14:07:44 +0300
commitb9efbe2b8f0177fa97bfab290d60858900aa196b (patch)
tree213bb673e66e8251a42eb8c9eb022192eaf98995
parent83c334ed521638c8dffe545ddf49d61430680308 (diff)
downloadlinux-b9efbe2b8f0177fa97bfab290d60858900aa196b.tar.xz
virtio_console: fix misc probe bugs
This fixes the following issue discovered by code review: after vqs have been created, a buggy device can send an interrupt. A control vq callback will then try to schedule control_work which has not been initialized yet. Similarly for config interrupt. Further, in and out vq callbacks invoke find_port_by_vq which attempts to take ports_lock which also has not been initialized. To fix, init all locks and work before creating vqs. Message-ID: <ad982e975a6160ad110c623c016041311ca15b4f.1726511547.git.mst@redhat.com> Fixes: 17634ba25544 ("virtio: console: Add a new MULTIPORT feature, support for generic ports") Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--drivers/char/virtio_console.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index de7d720d99fa..bcb05fc44c99 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -2007,25 +2007,27 @@ static int virtcons_probe(struct virtio_device *vdev)
multiport = true;
}
- err = init_vqs(portdev);
- if (err < 0) {
- dev_err(&vdev->dev, "Error %d initializing vqs\n", err);
- goto free_chrdev;
- }
-
spin_lock_init(&portdev->ports_lock);
INIT_LIST_HEAD(&portdev->ports);
INIT_LIST_HEAD(&portdev->list);
- virtio_device_ready(portdev->vdev);
-
INIT_WORK(&portdev->config_work, &config_work_handler);
INIT_WORK(&portdev->control_work, &control_work_handler);
if (multiport) {
spin_lock_init(&portdev->c_ivq_lock);
spin_lock_init(&portdev->c_ovq_lock);
+ }
+ err = init_vqs(portdev);
+ if (err < 0) {
+ dev_err(&vdev->dev, "Error %d initializing vqs\n", err);
+ goto free_chrdev;
+ }
+
+ virtio_device_ready(portdev->vdev);
+
+ if (multiport) {
err = fill_queue(portdev->c_ivq, &portdev->c_ivq_lock);
if (err < 0) {
dev_err(&vdev->dev,