From 1c8625aac0d204e567fcee5a8b4e9d0145f011c0 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Thu, 16 Sep 2021 11:34:58 +0200 Subject: virtio: implement remove callbacks virtio parent device drivers (e.g. PCI and MMIO) create child devices and free them on remove. The virtio drivers for the child devices (e.g. block and console) however don't unregister with their respective subsystems in the remove callbacks. So these subsystems may have stale pointers pointing at removed devices. This is especially problematic for the console driver, because the virtio console device_d will be removed, but the console itself remains registered leading to a use-after-free as soon as printf is invoked for the previously active console. This leads to a crash when typing reset in https://www.barebox.org/jsbarebox/?graphic=0 Fix this for all virtio drivers. Signed-off-by: Ahmad Fatoum Link: https://lore.barebox.org/20210916093458.21102-1-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer --- drivers/serial/virtio_console.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/serial') diff --git a/drivers/serial/virtio_console.c b/drivers/serial/virtio_console.c index a1331035d9..a4adb77610 100644 --- a/drivers/serial/virtio_console.c +++ b/drivers/serial/virtio_console.c @@ -134,6 +134,8 @@ static int virtcons_probe(struct virtio_device *vdev) virtcons = xzalloc(sizeof(*virtcons)); + vdev->priv = virtcons; + virtcons->in_vq = vqs[0]; virtcons->out_vq = vqs[1]; @@ -150,6 +152,17 @@ static int virtcons_probe(struct virtio_device *vdev) return console_register(&virtcons->cdev); } +static void virtcons_remove(struct virtio_device *vdev) +{ + struct virtio_console *virtcons = vdev->priv; + + vdev->config->reset(vdev); + console_unregister(&virtcons->cdev); + vdev->config->del_vqs(vdev); + + free(virtcons); +} + static struct virtio_device_id id_table[] = { { VIRTIO_ID_CONSOLE, VIRTIO_DEV_ANY_ID }, { 0 }, @@ -159,6 +172,7 @@ static struct virtio_driver virtio_console = { .driver.name = "virtio_console", .id_table = id_table, .probe = virtcons_probe, + .remove = virtcons_remove, }; device_virtio_driver(virtio_console); -- cgit v1.2.3