From 343dc693f7b79885197f9d37dd8b711b0e3ffc8f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 30 Sep 2017 11:15:52 +0300 Subject: misc: pci_endpoint_test: Prevent some integer overflows "size + max" can have an arithmetic overflow when we're allocating: orig_src_addr = dma_alloc_coherent(dev, size + alignment, ... Add a few checks to prevent that. Fixes: 13107c60681f ("misc: pci_endpoint_test: Add support to provide aligned buffer addresses") Signed-off-by: Dan Carpenter Signed-off-by: Bjorn Helgaas Acked-by: Kishon Vijay Abraham I --- drivers/misc/pci_endpoint_test.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index deb203026496..c0d323077ad0 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -226,6 +226,9 @@ static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size) u32 src_crc32; u32 dst_crc32; + if (size > SIZE_MAX - alignment) + goto err; + orig_src_addr = dma_alloc_coherent(dev, size + alignment, &orig_src_phys_addr, GFP_KERNEL); if (!orig_src_addr) { @@ -311,6 +314,9 @@ static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size) size_t alignment = test->alignment; u32 crc32; + if (size > SIZE_MAX - alignment) + goto err; + orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, GFP_KERNEL); if (!orig_addr) { @@ -369,6 +375,9 @@ static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size) size_t alignment = test->alignment; u32 crc32; + if (size > SIZE_MAX - alignment) + goto err; + orig_addr = dma_alloc_coherent(dev, size + alignment, &orig_phys_addr, GFP_KERNEL); if (!orig_addr) { -- cgit From a2db2663bd72053ca1e4b4f36dfd31ba233c3a65 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 30 Sep 2017 11:16:51 +0300 Subject: misc: pci_endpoint_test: Avoid triggering a BUG() If you call ida_simple_remove(&pci_endpoint_test_ida, id) with a negative "id" then it triggers an immediate BUG_ON(). Let's not allow that. Fixes: 2c156ac71c6b ("misc: Add host side PCI driver for PCI test function device") Signed-off-by: Dan Carpenter Signed-off-by: Bjorn Helgaas Acked-by: Kishon Vijay Abraham I --- drivers/misc/pci_endpoint_test.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index c0d323077ad0..d40a34f594c7 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -597,6 +597,8 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1) return; + if (id < 0) + return; misc_deregister(&test->miscdev); ida_simple_remove(&pci_endpoint_test_ida, id); -- cgit From 80068c93688f6143100859c4856f895801c1a1d9 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Wed, 11 Oct 2017 14:14:36 +0530 Subject: misc: pci_endpoint_test: Fix failure path return values in probe Return value of pci_endpoint_test_probe is not set properly in a couple of failure cases. Fix it here. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Bjorn Helgaas --- drivers/misc/pci_endpoint_test.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index d40a34f594c7..5e7af21686d6 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -542,6 +542,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, test->base = test->bar[test_reg_bar]; if (!test->base) { + err = -ENOMEM; dev_err(dev, "Cannot perform PCI test without BAR%d\n", test_reg_bar); goto err_iounmap; @@ -551,6 +552,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL); if (id < 0) { + err = id; dev_err(dev, "unable to get id\n"); goto err_iounmap; } -- cgit From 139838fffec40296d7235982a1a9b917ba31530f Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Wed, 11 Oct 2017 14:14:37 +0530 Subject: misc: pci_endpoint_test: Fix pci_endpoint_test not releasing resources on remove sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) in pci_endpoint_test_remove() returns 0, which results in returning early without releasing the resources. This is as a result of misc_device not having a valid name. Fix it here. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Bjorn Helgaas --- drivers/misc/pci_endpoint_test.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index 5e7af21686d6..bf64d150ec41 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -560,17 +560,24 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id); misc_device = &test->miscdev; misc_device->minor = MISC_DYNAMIC_MINOR; - misc_device->name = name; + misc_device->name = kstrdup(name, GFP_KERNEL); + if (!misc_device->name) { + err = -ENOMEM; + goto err_ida_remove; + } misc_device->fops = &pci_endpoint_test_fops, err = misc_register(misc_device); if (err) { dev_err(dev, "failed to register device\n"); - goto err_ida_remove; + goto err_kfree_name; } return 0; +err_kfree_name: + kfree(misc_device->name); + err_ida_remove: ida_simple_remove(&pci_endpoint_test_ida, id); @@ -603,6 +610,7 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) return; misc_deregister(&test->miscdev); + kfree(misc_device->name); ida_simple_remove(&pci_endpoint_test_ida, id); for (bar = BAR_0; bar <= BAR_5; bar++) { if (test->bar[bar]) -- cgit From b7636e816adcb52bc96b6fb7bc9d141cbfd17ddb Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Wed, 11 Oct 2017 14:14:38 +0530 Subject: misc: pci_endpoint_test: Fix BUG_ON error during pci_disable_msi() pci_disable_msi() throws a Kernel BUG if the driver has successfully requested an IRQ and not released it. Fix it here by freeing IRQs before invoking pci_disable_msi(). Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Bjorn Helgaas --- drivers/misc/pci_endpoint_test.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c index bf64d150ec41..320276f42653 100644 --- a/drivers/misc/pci_endpoint_test.c +++ b/drivers/misc/pci_endpoint_test.c @@ -92,6 +92,7 @@ struct pci_endpoint_test { void __iomem *bar[6]; struct completion irq_raised; int last_irq; + int num_irqs; /* mutex to protect the ioctls */ struct mutex mutex; struct miscdevice miscdev; @@ -513,6 +514,7 @@ static int pci_endpoint_test_probe(struct pci_dev *pdev, irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI); if (irq < 0) dev_err(dev, "failed to get MSI interrupts\n"); + test->num_irqs = irq; } err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler, @@ -587,6 +589,9 @@ err_iounmap: pci_iounmap(pdev, test->bar[bar]); } + for (i = 0; i < irq; i++) + devm_free_irq(dev, pdev->irq + i, test); + err_disable_msi: pci_disable_msi(pdev); pci_release_regions(pdev); @@ -600,6 +605,7 @@ err_disable_pdev: static void pci_endpoint_test_remove(struct pci_dev *pdev) { int id; + int i; enum pci_barno bar; struct pci_endpoint_test *test = pci_get_drvdata(pdev); struct miscdevice *misc_device = &test->miscdev; @@ -616,6 +622,8 @@ static void pci_endpoint_test_remove(struct pci_dev *pdev) if (test->bar[bar]) pci_iounmap(pdev, test->bar[bar]); } + for (i = 0; i < test->num_irqs; i++) + devm_free_irq(&pdev->dev, pdev->irq + i, test); pci_disable_msi(pdev); pci_release_regions(pdev); pci_disable_device(pdev); -- cgit