From 9d72fe1ce81bc757ecb6d57b58e5fd95b9ad1b26 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 10 Jun 2018 19:45:32 +0200 Subject: EDAC, altera: Fix an error handling path in altr_s10_sdram_probe() If regmap_write() fails, we should release some resources as done in all the other error handling paths of the function. Signed-off-by: Christophe JAILLET Reviewed-by: Thor Thayer Cc: linux-edac Link: http://lkml.kernel.org/r/20180610174532.22071-1-christophe.jaillet@wanadoo.fr Fixes: e9918d7fafae ("EDAC, altera: Handle SDRAM Uncorrectable Errors on Stratix10") Signed-off-by: Borislav Petkov --- drivers/edac/altera_edac.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index d0d5c4dbe097..5762c3c383f2 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -730,7 +730,8 @@ static int altr_s10_sdram_probe(struct platform_device *pdev) S10_DDR0_IRQ_MASK)) { edac_printk(KERN_ERR, EDAC_MC, "Error clearing SDRAM ECC count\n"); - return -ENODEV; + ret = -ENODEV; + goto err2; } if (regmap_update_bits(drvdata->mc_vbase, priv->ecc_irq_en_offset, -- cgit v1.2.3 From 4708aa85d50cc6e962dfa8acf5ad4e0d290a21db Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 12 Jun 2018 14:43:34 +0200 Subject: EDAC: Fix memleak in module init error path Make sure to use put_device() to free the initialised struct device so that resources managed by driver core also gets released in the event of a registration failure. Signed-off-by: Johan Hovold Cc: Denis Kirjanov Cc: Mauro Carvalho Chehab Cc: linux-edac Fixes: 2d56b109e3a5 ("EDAC: Handle error path in edac_mc_sysfs_init() properly") Link: http://lkml.kernel.org/r/20180612124335.6420-1-johan@kernel.org Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc_sysfs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 7481955160a4..20374b8248f0 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -1075,14 +1075,14 @@ int __init edac_mc_sysfs_init(void) err = device_add(mci_pdev); if (err < 0) - goto out_dev_free; + goto out_put_device; edac_dbg(0, "device %s created\n", dev_name(mci_pdev)); return 0; - out_dev_free: - kfree(mci_pdev); + out_put_device: + put_device(mci_pdev); out: return err; } -- cgit v1.2.3 From 6c974d4dfafe5e9ee754f2a6fba0eb1864f1649e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 12 Jun 2018 14:43:35 +0200 Subject: EDAC, i7core: Fix memleaks and use-after-free on probe and remove Make sure to free and deregister the addrmatch and chancounts devices allocated during probe in all error paths. Also fix use-after-free in a probe error path and in the remove success path where the devices were being put before before deregistration. Signed-off-by: Johan Hovold Cc: Mauro Carvalho Chehab Cc: linux-edac Fixes: 356f0a30860d ("i7core_edac: change the mem allocation scheme to make Documentation/kobject.txt happy") Link: http://lkml.kernel.org/r/20180612124335.6420-2-johan@kernel.org Signed-off-by: Borislav Petkov --- drivers/edac/i7core_edac.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 8ed4dd9c571b..8e120bf60624 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1177,15 +1177,14 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) rc = device_add(pvt->addrmatch_dev); if (rc < 0) - return rc; + goto err_put_addrmatch; if (!pvt->is_registered) { pvt->chancounts_dev = kzalloc(sizeof(*pvt->chancounts_dev), GFP_KERNEL); if (!pvt->chancounts_dev) { - put_device(pvt->addrmatch_dev); - device_del(pvt->addrmatch_dev); - return -ENOMEM; + rc = -ENOMEM; + goto err_del_addrmatch; } pvt->chancounts_dev->type = &all_channel_counts_type; @@ -1199,9 +1198,18 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) rc = device_add(pvt->chancounts_dev); if (rc < 0) - return rc; + goto err_put_chancounts; } return 0; + +err_put_chancounts: + put_device(pvt->chancounts_dev); +err_del_addrmatch: + device_del(pvt->addrmatch_dev); +err_put_addrmatch: + put_device(pvt->addrmatch_dev); + + return rc; } static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) @@ -1211,11 +1219,11 @@ static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) edac_dbg(1, "\n"); if (!pvt->is_registered) { - put_device(pvt->chancounts_dev); device_del(pvt->chancounts_dev); + put_device(pvt->chancounts_dev); } - put_device(pvt->addrmatch_dev); device_del(pvt->addrmatch_dev); + put_device(pvt->addrmatch_dev); } /**************************************************************************** -- cgit v1.2.3 From 6663484b4e2d98f5609dc1b90fe4c242dd8fe18a Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 29 Jun 2018 11:48:50 -0700 Subject: EDAC, thunderx: Remove VLA usage In the quest to remove all stack VLA usage from the kernel[1], switch to using a kmalloc-allocated buffer instead of stack space. This should be fine since the existing routine is allocating memory too. Signed-off-by: Kees Cook Acked-by: Jan Glauber Cc: David Daney Cc: linux-edac Link: http://lkml.kernel.org/r/20180629184850.GA37464@beast Link: https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com [1] Signed-off-by: Borislav Petkov --- drivers/edac/thunderx_edac.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c index 4803c6468bab..c009d94f40c5 100644 --- a/drivers/edac/thunderx_edac.c +++ b/drivers/edac/thunderx_edac.c @@ -408,26 +408,29 @@ static ssize_t thunderx_lmc_inject_ecc_write(struct file *file, size_t count, loff_t *ppos) { struct thunderx_lmc *lmc = file->private_data; - unsigned int cline_size = cache_line_size(); - - u8 tmp[cline_size]; + u8 *tmp; void __iomem *addr; unsigned int offs, timeout = 100000; atomic_set(&lmc->ecc_int, 0); lmc->mem = alloc_pages_node(lmc->node, GFP_KERNEL, 0); - if (!lmc->mem) return -ENOMEM; + tmp = kmalloc(cline_size, GFP_KERNEL); + if (!tmp) { + __free_pages(lmc->mem, 0); + return -ENOMEM; + } + addr = page_address(lmc->mem); while (!atomic_read(&lmc->ecc_int) && timeout--) { stop_machine(inject_ecc_fn, lmc, NULL); - for (offs = 0; offs < PAGE_SIZE; offs += sizeof(tmp)) { + for (offs = 0; offs < PAGE_SIZE; offs += cline_size) { /* * Do a load from the previously rigged location * This should generate an error interrupt. @@ -437,6 +440,7 @@ static ssize_t thunderx_lmc_inject_ecc_write(struct file *file, } } + kfree(tmp); __free_pages(lmc->mem, 0); return count; -- cgit v1.2.3 From 190bd6e98afc512fb16d4a471acd488e36141637 Mon Sep 17 00:00:00 2001 From: Masayoshi Mizuma Date: Tue, 24 Jul 2018 15:02:13 -0400 Subject: EDAC, sb_edac: Add support for systems with segmented PCI buses Extend the driver to check whether segment number and bus number matches when deciding how to group memory controller PCI devices to CPU sockets. Signed-off-by: Masayoshi Mizuma Reviewed-by: Tony Luck Cc: Mauro Carvalho Chehab Cc: linux-edac Link: http://lkml.kernel.org/r/20180724190213.26359-1-msys.mizuma@gmail.com [ Cleanup commit message. ] Signed-off-by: Borislav Petkov --- drivers/edac/sb_edac.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 4a89c8093307..07726fb00321 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -352,6 +352,7 @@ struct pci_id_table { struct sbridge_dev { struct list_head list; + int seg; u8 bus, mc; u8 node_id, source_id; struct pci_dev **pdev; @@ -729,7 +730,8 @@ static inline int numcol(u32 mtr) return 1 << cols; } -static struct sbridge_dev *get_sbridge_dev(u8 bus, enum domain dom, int multi_bus, +static struct sbridge_dev *get_sbridge_dev(int seg, u8 bus, enum domain dom, + int multi_bus, struct sbridge_dev *prev) { struct sbridge_dev *sbridge_dev; @@ -747,14 +749,15 @@ static struct sbridge_dev *get_sbridge_dev(u8 bus, enum domain dom, int multi_bu : sbridge_edac_list.next, struct sbridge_dev, list); list_for_each_entry_from(sbridge_dev, &sbridge_edac_list, list) { - if (sbridge_dev->bus == bus && (dom == SOCK || dom == sbridge_dev->dom)) + if ((sbridge_dev->seg == seg) && (sbridge_dev->bus == bus) && + (dom == SOCK || dom == sbridge_dev->dom)) return sbridge_dev; } return NULL; } -static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom, +static struct sbridge_dev *alloc_sbridge_dev(int seg, u8 bus, enum domain dom, const struct pci_id_table *table) { struct sbridge_dev *sbridge_dev; @@ -771,6 +774,7 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom, return NULL; } + sbridge_dev->seg = seg; sbridge_dev->bus = bus; sbridge_dev->dom = dom; sbridge_dev->n_devs = table->n_devs_per_imc; @@ -2246,6 +2250,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev, struct sbridge_dev *sbridge_dev = NULL; const struct pci_id_descr *dev_descr = &table->descr[devno]; struct pci_dev *pdev = NULL; + int seg = 0; u8 bus = 0; int i = 0; @@ -2276,10 +2281,12 @@ static int sbridge_get_onedevice(struct pci_dev **prev, /* End of list, leave */ return -ENODEV; } + seg = pci_domain_nr(pdev->bus); bus = pdev->bus->number; next_imc: - sbridge_dev = get_sbridge_dev(bus, dev_descr->dom, multi_bus, sbridge_dev); + sbridge_dev = get_sbridge_dev(seg, bus, dev_descr->dom, + multi_bus, sbridge_dev); if (!sbridge_dev) { /* If the HA1 wasn't found, don't create EDAC second memory controller */ if (dev_descr->dom == IMC1 && devno != 1) { @@ -2292,7 +2299,7 @@ next_imc: if (dev_descr->dom == SOCK) goto out_imc; - sbridge_dev = alloc_sbridge_dev(bus, dev_descr->dom, table); + sbridge_dev = alloc_sbridge_dev(seg, bus, dev_descr->dom, table); if (!sbridge_dev) { pci_dev_put(pdev); return -ENOMEM; -- cgit v1.2.3