All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm: qxl: Fix error handling at qxl_device_init
@ 2018-07-27 11:54 Anton Vasilyev
  2018-08-10  6:03 ` Gerd Hoffmann
  2018-08-10  6:03   ` Gerd Hoffmann
  0 siblings, 2 replies; 5+ messages in thread
From: Anton Vasilyev @ 2018-07-27 11:54 UTC (permalink / raw)
  To: Dave Airlie
  Cc: Anton Vasilyev, Gerd Hoffmann, David Airlie, virtualization,
	dri-devel, linux-kernel, ldv-project

If qxl_device_init fails on creating resources and does not report it,
then qxl module will catch null pointer exception on remove, or on
probe's error path.

The patch adds error path with resources release into qxl_device_init.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Anton Vasilyev <vasilyev@ispras.ru>
---
 drivers/gpu/drm/qxl/qxl_kms.c | 80 ++++++++++++++++++++++++++++++++---
 1 file changed, 73 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
index 771250aed78d..e25c589d5f50 100644
--- a/drivers/gpu/drm/qxl/qxl_kms.c
+++ b/drivers/gpu/drm/qxl/qxl_kms.c
@@ -102,8 +102,10 @@ int qxl_device_init(struct qxl_device *qdev,
 	int r, sb;
 
 	r = drm_dev_init(&qdev->ddev, drv, &pdev->dev);
-	if (r)
-		return r;
+	if (r) {
+		pr_err("Unable to init drm dev");
+		goto error;
+	}
 
 	qdev->ddev.pdev = pdev;
 	pci_set_drvdata(pdev, &qdev->ddev);
@@ -121,6 +123,11 @@ int qxl_device_init(struct qxl_device *qdev,
 	qdev->io_base = pci_resource_start(pdev, 3);
 
 	qdev->vram_mapping = io_mapping_create_wc(qdev->vram_base, pci_resource_len(pdev, 0));
+	if (!qdev->vram_mapping) {
+		pr_err("Unable to create vram_mapping");
+		r = -ENOMEM;
+		goto error;
+	}
 
 	if (pci_resource_len(pdev, 4) > 0) {
 		/* 64bit surface bar present */
@@ -139,6 +146,11 @@ int qxl_device_init(struct qxl_device *qdev,
 		qdev->surface_mapping =
 			io_mapping_create_wc(qdev->surfaceram_base,
 					     qdev->surfaceram_size);
+		if (!qdev->surface_mapping) {
+			pr_err("Unable to create surface_mapping");
+			r = -ENOMEM;
+			goto vram_mapping_free;
+		}
 	}
 
 	DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk, %s)\n",
@@ -155,20 +167,29 @@ int qxl_device_init(struct qxl_device *qdev,
 	qdev->rom = ioremap(qdev->rom_base, qdev->rom_size);
 	if (!qdev->rom) {
 		pr_err("Unable to ioremap ROM\n");
-		return -ENOMEM;
+		r = -ENOMEM;
+		goto surface_mapping_free;
 	}
 
-	qxl_check_device(qdev);
+	if (!qxl_check_device(qdev)) {
+		r = -ENODEV;
+		goto surface_mapping_free;
+	}
 
 	r = qxl_bo_init(qdev);
 	if (r) {
 		DRM_ERROR("bo init failed %d\n", r);
-		return r;
+		goto rom_unmap;
 	}
 
 	qdev->ram_header = ioremap(qdev->vram_base +
 				   qdev->rom->ram_header_offset,
 				   sizeof(*qdev->ram_header));
+	if (!qdev->ram_header) {
+		DRM_ERROR("Unable to ioremap RAM header\n");
+		r = -ENOMEM;
+		goto bo_fini;
+	}
 
 	qdev->command_ring = qxl_ring_create(&(qdev->ram_header->cmd_ring_hdr),
 					     sizeof(struct qxl_command),
@@ -176,6 +197,11 @@ int qxl_device_init(struct qxl_device *qdev,
 					     qdev->io_base + QXL_IO_NOTIFY_CMD,
 					     false,
 					     &qdev->display_event);
+	if (!qdev->command_ring) {
+		DRM_ERROR("Unable to create command ring\n");
+		r = -ENOMEM;
+		goto ram_header_unmap;
+	}
 
 	qdev->cursor_ring = qxl_ring_create(
 				&(qdev->ram_header->cursor_ring_hdr),
@@ -185,12 +211,23 @@ int qxl_device_init(struct qxl_device *qdev,
 				false,
 				&qdev->cursor_event);
 
+	if (!qdev->cursor_ring) {
+		DRM_ERROR("Unable to create cursor ring\n");
+		r = -ENOMEM;
+		goto command_ring_free;
+	}
+
 	qdev->release_ring = qxl_ring_create(
 				&(qdev->ram_header->release_ring_hdr),
 				sizeof(uint64_t),
 				QXL_RELEASE_RING_SIZE, 0, true,
 				NULL);
 
+	if (!qdev->release_ring) {
+		DRM_ERROR("Unable to create release ring\n");
+		r = -ENOMEM;
+		goto cursor_ring_free;
+	}
 	/* TODO - slot initialization should happen on reset. where is our
 	 * reset handler? */
 	qdev->n_mem_slots = qdev->rom->slots_end;
@@ -203,6 +240,12 @@ int qxl_device_init(struct qxl_device *qdev,
 		kmalloc_array(qdev->n_mem_slots, sizeof(struct qxl_memslot),
 			      GFP_KERNEL);
 
+	if (!qdev->mem_slots) {
+		DRM_ERROR("Unable to alloc mem slots\n");
+		r = -ENOMEM;
+		goto release_ring_free;
+	}
+
 	idr_init(&qdev->release_idr);
 	spin_lock_init(&qdev->release_idr_lock);
 	spin_lock_init(&qdev->release_lock);
@@ -218,8 +261,10 @@ int qxl_device_init(struct qxl_device *qdev,
 
 	/* must initialize irq before first async io - slot creation */
 	r = qxl_irq_init(qdev);
-	if (r)
-		return r;
+	if (r) {
+		DRM_ERROR("Unable to init qxl irq\n");
+		goto mem_slots_free;
+	}
 
 	/*
 	 * Note that virtual is surface0. We rely on the single ioremap done
@@ -243,6 +288,27 @@ int qxl_device_init(struct qxl_device *qdev,
 	INIT_WORK(&qdev->gc_work, qxl_gc_work);
 
 	return 0;
+
+mem_slots_free:
+	kfree(qdev->mem_slots);
+release_ring_free:
+	qxl_ring_free(qdev->release_ring);
+cursor_ring_free:
+	qxl_ring_free(qdev->cursor_ring);
+command_ring_free:
+	qxl_ring_free(qdev->command_ring);
+ram_header_unmap:
+	iounmap(qdev->ram_header);
+bo_fini:
+	qxl_bo_fini(qdev);
+rom_unmap:
+	iounmap(qdev->rom);
+surface_mapping_free:
+	io_mapping_free(qdev->surface_mapping);
+vram_mapping_free:
+	io_mapping_free(qdev->vram_mapping);
+error:
+	return r;
 }
 
 void qxl_device_fini(struct qxl_device *qdev)
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] drm: qxl: Fix error handling at qxl_device_init
  2018-07-27 11:54 [PATCH] drm: qxl: Fix error handling at qxl_device_init Anton Vasilyev
@ 2018-08-10  6:03   ` Gerd Hoffmann
  2018-08-10  6:03   ` Gerd Hoffmann
  1 sibling, 0 replies; 5+ messages in thread
From: Gerd Hoffmann @ 2018-08-10  6:03 UTC (permalink / raw)
  To: Anton Vasilyev
  Cc: Dave Airlie, David Airlie, virtualization, dri-devel,
	linux-kernel, ldv-project

On Fri, Jul 27, 2018 at 02:54:40PM +0300, Anton Vasilyev wrote:
> If qxl_device_init fails on creating resources and does not report it,
> then qxl module will catch null pointer exception on remove, or on
> probe's error path.
> 
> The patch adds error path with resources release into qxl_device_init.
> 
> Found by Linux Driver Verification project (linuxtesting.org).

Pushed to drm-misc-next.

thanks,
  Gerd


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] drm: qxl: Fix error handling at qxl_device_init
  2018-07-27 11:54 [PATCH] drm: qxl: Fix error handling at qxl_device_init Anton Vasilyev
@ 2018-08-10  6:03 ` Gerd Hoffmann
  2018-08-10  6:03   ` Gerd Hoffmann
  1 sibling, 0 replies; 5+ messages in thread
From: Gerd Hoffmann @ 2018-08-10  6:03 UTC (permalink / raw)
  To: Anton Vasilyev
  Cc: ldv-project, David Airlie, linux-kernel, dri-devel,
	virtualization, Dave Airlie

On Fri, Jul 27, 2018 at 02:54:40PM +0300, Anton Vasilyev wrote:
> If qxl_device_init fails on creating resources and does not report it,
> then qxl module will catch null pointer exception on remove, or on
> probe's error path.
> 
> The patch adds error path with resources release into qxl_device_init.
> 
> Found by Linux Driver Verification project (linuxtesting.org).

Pushed to drm-misc-next.

thanks,
  Gerd

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] drm: qxl: Fix error handling at qxl_device_init
@ 2018-08-10  6:03   ` Gerd Hoffmann
  0 siblings, 0 replies; 5+ messages in thread
From: Gerd Hoffmann @ 2018-08-10  6:03 UTC (permalink / raw)
  To: Anton Vasilyev
  Cc: ldv-project, David Airlie, linux-kernel, dri-devel,
	virtualization, Dave Airlie

On Fri, Jul 27, 2018 at 02:54:40PM +0300, Anton Vasilyev wrote:
> If qxl_device_init fails on creating resources and does not report it,
> then qxl module will catch null pointer exception on remove, or on
> probe's error path.
> 
> The patch adds error path with resources release into qxl_device_init.
> 
> Found by Linux Driver Verification project (linuxtesting.org).

Pushed to drm-misc-next.

thanks,
  Gerd

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] drm: qxl: Fix error handling at qxl_device_init
@ 2018-07-27 11:54 Anton Vasilyev
  0 siblings, 0 replies; 5+ messages in thread
From: Anton Vasilyev @ 2018-07-27 11:54 UTC (permalink / raw)
  To: Dave Airlie
  Cc: ldv-project, David Airlie, linux-kernel, dri-devel,
	virtualization, Anton Vasilyev

If qxl_device_init fails on creating resources and does not report it,
then qxl module will catch null pointer exception on remove, or on
probe's error path.

The patch adds error path with resources release into qxl_device_init.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Anton Vasilyev <vasilyev@ispras.ru>
---
 drivers/gpu/drm/qxl/qxl_kms.c | 80 ++++++++++++++++++++++++++++++++---
 1 file changed, 73 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
index 771250aed78d..e25c589d5f50 100644
--- a/drivers/gpu/drm/qxl/qxl_kms.c
+++ b/drivers/gpu/drm/qxl/qxl_kms.c
@@ -102,8 +102,10 @@ int qxl_device_init(struct qxl_device *qdev,
 	int r, sb;
 
 	r = drm_dev_init(&qdev->ddev, drv, &pdev->dev);
-	if (r)
-		return r;
+	if (r) {
+		pr_err("Unable to init drm dev");
+		goto error;
+	}
 
 	qdev->ddev.pdev = pdev;
 	pci_set_drvdata(pdev, &qdev->ddev);
@@ -121,6 +123,11 @@ int qxl_device_init(struct qxl_device *qdev,
 	qdev->io_base = pci_resource_start(pdev, 3);
 
 	qdev->vram_mapping = io_mapping_create_wc(qdev->vram_base, pci_resource_len(pdev, 0));
+	if (!qdev->vram_mapping) {
+		pr_err("Unable to create vram_mapping");
+		r = -ENOMEM;
+		goto error;
+	}
 
 	if (pci_resource_len(pdev, 4) > 0) {
 		/* 64bit surface bar present */
@@ -139,6 +146,11 @@ int qxl_device_init(struct qxl_device *qdev,
 		qdev->surface_mapping =
 			io_mapping_create_wc(qdev->surfaceram_base,
 					     qdev->surfaceram_size);
+		if (!qdev->surface_mapping) {
+			pr_err("Unable to create surface_mapping");
+			r = -ENOMEM;
+			goto vram_mapping_free;
+		}
 	}
 
 	DRM_DEBUG_KMS("qxl: vram %llx-%llx(%dM %dk), surface %llx-%llx(%dM %dk, %s)\n",
@@ -155,20 +167,29 @@ int qxl_device_init(struct qxl_device *qdev,
 	qdev->rom = ioremap(qdev->rom_base, qdev->rom_size);
 	if (!qdev->rom) {
 		pr_err("Unable to ioremap ROM\n");
-		return -ENOMEM;
+		r = -ENOMEM;
+		goto surface_mapping_free;
 	}
 
-	qxl_check_device(qdev);
+	if (!qxl_check_device(qdev)) {
+		r = -ENODEV;
+		goto surface_mapping_free;
+	}
 
 	r = qxl_bo_init(qdev);
 	if (r) {
 		DRM_ERROR("bo init failed %d\n", r);
-		return r;
+		goto rom_unmap;
 	}
 
 	qdev->ram_header = ioremap(qdev->vram_base +
 				   qdev->rom->ram_header_offset,
 				   sizeof(*qdev->ram_header));
+	if (!qdev->ram_header) {
+		DRM_ERROR("Unable to ioremap RAM header\n");
+		r = -ENOMEM;
+		goto bo_fini;
+	}
 
 	qdev->command_ring = qxl_ring_create(&(qdev->ram_header->cmd_ring_hdr),
 					     sizeof(struct qxl_command),
@@ -176,6 +197,11 @@ int qxl_device_init(struct qxl_device *qdev,
 					     qdev->io_base + QXL_IO_NOTIFY_CMD,
 					     false,
 					     &qdev->display_event);
+	if (!qdev->command_ring) {
+		DRM_ERROR("Unable to create command ring\n");
+		r = -ENOMEM;
+		goto ram_header_unmap;
+	}
 
 	qdev->cursor_ring = qxl_ring_create(
 				&(qdev->ram_header->cursor_ring_hdr),
@@ -185,12 +211,23 @@ int qxl_device_init(struct qxl_device *qdev,
 				false,
 				&qdev->cursor_event);
 
+	if (!qdev->cursor_ring) {
+		DRM_ERROR("Unable to create cursor ring\n");
+		r = -ENOMEM;
+		goto command_ring_free;
+	}
+
 	qdev->release_ring = qxl_ring_create(
 				&(qdev->ram_header->release_ring_hdr),
 				sizeof(uint64_t),
 				QXL_RELEASE_RING_SIZE, 0, true,
 				NULL);
 
+	if (!qdev->release_ring) {
+		DRM_ERROR("Unable to create release ring\n");
+		r = -ENOMEM;
+		goto cursor_ring_free;
+	}
 	/* TODO - slot initialization should happen on reset. where is our
 	 * reset handler? */
 	qdev->n_mem_slots = qdev->rom->slots_end;
@@ -203,6 +240,12 @@ int qxl_device_init(struct qxl_device *qdev,
 		kmalloc_array(qdev->n_mem_slots, sizeof(struct qxl_memslot),
 			      GFP_KERNEL);
 
+	if (!qdev->mem_slots) {
+		DRM_ERROR("Unable to alloc mem slots\n");
+		r = -ENOMEM;
+		goto release_ring_free;
+	}
+
 	idr_init(&qdev->release_idr);
 	spin_lock_init(&qdev->release_idr_lock);
 	spin_lock_init(&qdev->release_lock);
@@ -218,8 +261,10 @@ int qxl_device_init(struct qxl_device *qdev,
 
 	/* must initialize irq before first async io - slot creation */
 	r = qxl_irq_init(qdev);
-	if (r)
-		return r;
+	if (r) {
+		DRM_ERROR("Unable to init qxl irq\n");
+		goto mem_slots_free;
+	}
 
 	/*
 	 * Note that virtual is surface0. We rely on the single ioremap done
@@ -243,6 +288,27 @@ int qxl_device_init(struct qxl_device *qdev,
 	INIT_WORK(&qdev->gc_work, qxl_gc_work);
 
 	return 0;
+
+mem_slots_free:
+	kfree(qdev->mem_slots);
+release_ring_free:
+	qxl_ring_free(qdev->release_ring);
+cursor_ring_free:
+	qxl_ring_free(qdev->cursor_ring);
+command_ring_free:
+	qxl_ring_free(qdev->command_ring);
+ram_header_unmap:
+	iounmap(qdev->ram_header);
+bo_fini:
+	qxl_bo_fini(qdev);
+rom_unmap:
+	iounmap(qdev->rom);
+surface_mapping_free:
+	io_mapping_free(qdev->surface_mapping);
+vram_mapping_free:
+	io_mapping_free(qdev->vram_mapping);
+error:
+	return r;
 }
 
 void qxl_device_fini(struct qxl_device *qdev)
-- 
2.18.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-08-10  6:03 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-27 11:54 [PATCH] drm: qxl: Fix error handling at qxl_device_init Anton Vasilyev
2018-08-10  6:03 ` Gerd Hoffmann
2018-08-10  6:03 ` Gerd Hoffmann
2018-08-10  6:03   ` Gerd Hoffmann
2018-07-27 11:54 Anton Vasilyev

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.