diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2024-09-16 14:16:44 -0400 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2024-09-25 07:07:44 -0400 |
commit | b9efbe2b8f0177fa97bfab290d60858900aa196b (patch) | |
tree | 213bb673e66e8251a42eb8c9eb022192eaf98995 /drivers/char/virtio_console.c | |
parent | 83c334ed521638c8dffe545ddf49d61430680308 (diff) | |
download | lwn-b9efbe2b8f0177fa97bfab290d60858900aa196b.tar.gz lwn-b9efbe2b8f0177fa97bfab290d60858900aa196b.zip |
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>
Diffstat (limited to 'drivers/char/virtio_console.c')
-rw-r--r-- | drivers/char/virtio_console.c | 18 |
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, |