virtio-mmio: fix memory leak of vm_dev
commitfab7f25922
upstream. With the recent removal of vm_dev from devres its memory is only freed via the callback virtio_mmio_release_dev. However, this only takes effect after device_add is called by register_virtio_device. Until then it's an unmanaged resource and must be explicitly freed on error exit. This bug was discovered and resolved using Coverity Static Analysis Security Testing (SAST) by Synopsys, Inc. Cc: stable@vger.kernel.org Fixes:55c91fedd0
("virtio-mmio: don't break lifecycle of vm_dev") Signed-off-by: Maximilian Heyne <mheyne@amazon.de> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Tested-by: Catalin Marinas <catalin.marinas@arm.com> Reviewed-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Message-Id: <20230911090328.40538-1-mheyne@amazon.de> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
19b30a8790
commit
a9d4a1ea67
@ -614,14 +614,17 @@ static int virtio_mmio_probe(struct platform_device *pdev)
|
|||||||
spin_lock_init(&vm_dev->lock);
|
spin_lock_init(&vm_dev->lock);
|
||||||
|
|
||||||
vm_dev->base = devm_platform_ioremap_resource(pdev, 0);
|
vm_dev->base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
if (IS_ERR(vm_dev->base))
|
if (IS_ERR(vm_dev->base)) {
|
||||||
return PTR_ERR(vm_dev->base);
|
rc = PTR_ERR(vm_dev->base);
|
||||||
|
goto free_vm_dev;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check magic value */
|
/* Check magic value */
|
||||||
magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE);
|
magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE);
|
||||||
if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) {
|
if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) {
|
||||||
dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic);
|
dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic);
|
||||||
return -ENODEV;
|
rc = -ENODEV;
|
||||||
|
goto free_vm_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check device version */
|
/* Check device version */
|
||||||
@ -629,7 +632,8 @@ static int virtio_mmio_probe(struct platform_device *pdev)
|
|||||||
if (vm_dev->version < 1 || vm_dev->version > 2) {
|
if (vm_dev->version < 1 || vm_dev->version > 2) {
|
||||||
dev_err(&pdev->dev, "Version %ld not supported!\n",
|
dev_err(&pdev->dev, "Version %ld not supported!\n",
|
||||||
vm_dev->version);
|
vm_dev->version);
|
||||||
return -ENXIO;
|
rc = -ENXIO;
|
||||||
|
goto free_vm_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID);
|
vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID);
|
||||||
@ -638,7 +642,8 @@ static int virtio_mmio_probe(struct platform_device *pdev)
|
|||||||
* virtio-mmio device with an ID 0 is a (dummy) placeholder
|
* virtio-mmio device with an ID 0 is a (dummy) placeholder
|
||||||
* with no function. End probing now with no error reported.
|
* with no function. End probing now with no error reported.
|
||||||
*/
|
*/
|
||||||
return -ENODEV;
|
rc = -ENODEV;
|
||||||
|
goto free_vm_dev;
|
||||||
}
|
}
|
||||||
vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID);
|
vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID);
|
||||||
|
|
||||||
@ -668,6 +673,10 @@ static int virtio_mmio_probe(struct platform_device *pdev)
|
|||||||
put_device(&vm_dev->vdev.dev);
|
put_device(&vm_dev->vdev.dev);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
free_vm_dev:
|
||||||
|
kfree(vm_dev);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int virtio_mmio_remove(struct platform_device *pdev)
|
static int virtio_mmio_remove(struct platform_device *pdev)
|
||||||
|
Reference in New Issue
Block a user