From 311bd84247ee0bedae6cdfbfc5e2c3450f9decd1 Mon Sep 17 00:00:00 2001 From: Konstantin Khlebnikov Date: Fri, 14 Dec 2012 15:03:10 +0400 Subject: EDAC: Fix kernel panic on module unloading This patch fixes use-after-free and double-free bugs in edac_mc_sysfs_exit(). mci_pdev has single reference and put_device() calls mc_attr_release() which calls kfree(). The following device_del() works with already released memory. An another kfree() in edac_mc_sysfs_exit() releses the same memory again. Great. Signed-off-by: Konstantin Khlebnikov Cc: stable@vger.kernel.org # 3.[67] Cc: Denis Kirjanov Cc: Mauro Carvalho Chehab Link: http://lkml.kernel.org/r/20121214110310.11019.21098.stgit@zurg Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc_sysfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index de2df92f9c77..a3b0119ecb00 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -1159,8 +1159,7 @@ int __init edac_mc_sysfs_init(void) void __exit edac_mc_sysfs_exit(void) { - put_device(mci_pdev); device_del(mci_pdev); + put_device(mci_pdev); edac_put_sysfs_subsys(); - kfree(mci_pdev); } -- cgit v1.2.3 From 5445166384755adc39c772acccca87ad5747be52 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 18 Dec 2012 22:02:56 +0100 Subject: EDAC: Fix EDAC Kconfig menu After f65aad41772f("MIPS: Cavium: Add EDAC support."), when entering the "Device Drivers" toplevel menu in menuconfig, the suboptions behind EDAC appeared merged with the rest of the device drivers types. This was because the menuconfig option EDAC is querying an EDAC_SUPPORT Kconfig bool which was defined after the menu definition. When pushing EDAC_SUPPORT up, before the menu definition, the variable is defined earlier and the above menuconfig artifact doesn't happen. Drop a useless menuconfig comment while at it. Cc: Ralf Baechle Signed-off-by: Borislav Petkov --- drivers/edac/Kconfig | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 4c6c876d9dc3..66719925970f 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -4,6 +4,9 @@ # Licensed and distributed under the GPL # +config EDAC_SUPPORT + bool + menuconfig EDAC bool "EDAC (Error Detection And Correction) reporting" depends on HAS_IOMEM @@ -27,13 +30,8 @@ menuconfig EDAC There is also a mailing list for the EDAC project, which can be found via the sourceforge page. -config EDAC_SUPPORT - bool - if EDAC -comment "Reporting subsystems" - config EDAC_LEGACY_SYSFS bool "EDAC legacy sysfs" default y -- cgit v1.2.3 From 44d22e2404b3ce93a314654962d31acc8afcdd62 Mon Sep 17 00:00:00 2001 From: Lans Zhang Date: Mon, 24 Dec 2012 14:01:34 +0100 Subject: EDAC: Cleanup device deregistering path Use device_unregister to replace put_device + device_del for cleanup, and fix the potential use after free. Signed-off-by: Lans Zhang Signed-off-by: Borislav Petkov --- drivers/edac/edac_mc_sysfs.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index a3b0119ecb00..0ca1ca71157f 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -472,8 +472,7 @@ static void edac_delete_csrow_objects(struct mem_ctl_info *mci) device_remove_file(&csrow->dev, dynamic_csrow_ce_count_attr[chan]); } - put_device(&mci->csrows[i]->dev); - device_del(&mci->csrows[i]->dev); + device_unregister(&mci->csrows[i]->dev); } } #endif @@ -1055,11 +1054,9 @@ fail: struct dimm_info *dimm = mci->dimms[i]; if (dimm->nr_pages == 0) continue; - put_device(&dimm->dev); - device_del(&dimm->dev); + device_unregister(&dimm->dev); } - put_device(&mci->dev); - device_del(&mci->dev); + device_unregister(&mci->dev); bus_unregister(&mci->bus); kfree(mci->bus.name); return err; @@ -1086,16 +1083,14 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) if (dimm->nr_pages == 0) continue; edac_dbg(0, "removing device %s\n", dev_name(&dimm->dev)); - put_device(&dimm->dev); - device_del(&dimm->dev); + device_unregister(&dimm->dev); } } void edac_unregister_sysfs(struct mem_ctl_info *mci) { edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev)); - put_device(&mci->dev); - device_del(&mci->dev); + device_unregister(&mci->dev); bus_unregister(&mci->bus); kfree(mci->bus.name); } @@ -1159,7 +1154,6 @@ int __init edac_mc_sysfs_init(void) void __exit edac_mc_sysfs_exit(void) { - device_del(mci_pdev); - put_device(mci_pdev); + device_unregister(mci_pdev); edac_put_sysfs_subsys(); } -- cgit v1.2.3