From 7faefea66a6d1f0d9da0a18615f57dc969e00d99 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 10 Aug 2010 18:03:10 -0700 Subject: [PATCH] ipmi: fix memleaking for add_smi when duplicating happen Free the temporary info struct when we have duplicated ones. Signed-off-by: Yinghai Lu Cc: Corey Minyard Cc: Matthew Garrett Cc: Len Brown Cc: Myron Stowe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 35 +++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index ecfe43beb9c2..6c2daed531df 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1804,9 +1804,12 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) info->irq_setup = std_irq_setup; info->slave_addr = ipmb; - if (!add_smi(info)) + if (!add_smi(info)) { if (try_smi_init(info)) cleanup_one_si(info); + } else { + kfree(info); + } } else { /* remove */ struct smi_info *e, *tmp_e; @@ -1890,9 +1893,12 @@ static __devinit void hardcode_find_bmc(void) info->irq_setup = std_irq_setup; info->slave_addr = slave_addrs[i]; - if (!add_smi(info)) + if (!add_smi(info)) { if (try_smi_init(info)) cleanup_one_si(info); + } else { + kfree(info); + } } } @@ -2082,7 +2088,8 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) } info->io.addr_data = spmi->addr.address; - add_smi(info); + if (add_smi(info)) + kfree(info); return 0; } @@ -2198,7 +2205,10 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, res, info->io.regsize, info->io.regspacing, info->irq); - return add_smi(info); + if (add_smi(info)) + goto err_free; + + return 0; err_free: kfree(info); @@ -2356,7 +2366,8 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) if (info->irq) info->irq_setup = std_irq_setup; - add_smi(info); + if (add_smi(info)) + kfree(info); } static void __devinit dmi_find_bmc(void) @@ -2462,7 +2473,10 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, &pdev->resource[0], info->io.regsize, info->io.regspacing, info->irq); - return add_smi(info); + if (add_smi(info)) + kfree(info); + + return 0; } static void __devexit ipmi_pci_remove(struct pci_dev *pdev) @@ -2575,7 +2589,12 @@ static int __devinit ipmi_of_probe(struct of_device *dev, dev_set_drvdata(&dev->dev, info); - return add_smi(info); + if (add_smi(info)) { + kfree(info); + return -EBUSY; + } + + return 0; } static int __devexit ipmi_of_remove(struct of_device *dev) @@ -3008,6 +3027,8 @@ static __devinit void default_find_bmc(void) info->io.addr_data); } else cleanup_one_si(info); + } else { + kfree(info); } } }