From mboxrd@z Thu Jan 1 00:00:00 1970 From: Thomas Gleixner Subject: [patch 01/47] x86: Plug memory leak in sparse irq Date: Thu, 30 Sep 2010 23:14:33 -0000 Message-ID: <20100930221738.572997675@linutronix.de> References: <20100930221351.682772535@linutronix.de> Return-path: Received: from www.tglx.de ([62.245.132.106]:34739 "EHLO www.tglx.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751150Ab0I3XZP (ORCPT ); Thu, 30 Sep 2010 19:25:15 -0400 Content-Disposition: inline; filename=x86-plug-memory-leak-in-sparse-irq.patch Sender: linux-arch-owner@vger.kernel.org List-ID: To: LKML Cc: linux-arch@vger.kernel.org, Linus Torvalds , Andrew Morton , x86@kernel.org, Peter Zijlstra , Benjamin Herrenschmidt , Paul Mundt , Russell King , David Woodhouse , Jesse Barnes , Yinghai Lu , Grant Likely , "Eric W. Biederman" , Yinghai Lu , stable@kernel.org free_irq_cfg() is not freeing the cpumask_vars in irq_cfg. Fixing this triggers a use after free caused by the fact that copying struct irq_cfg is done with memcpy, which copies the pointer not the cpumask. Fix both places. Signed-off-by: Thomas Gleixner Cc: Yinghai Lu LKML-Reference: Signed-off-by: Thomas Gleixner Cc: stable@kernel.org --- arch/x86/kernel/apic/io_apic.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) Index: linux-2.6-tip/arch/x86/kernel/apic/io_apic.c =================================================================== --- linux-2.6-tip.orig/arch/x86/kernel/apic/io_apic.c +++ linux-2.6-tip/arch/x86/kernel/apic/io_apic.c @@ -307,14 +307,19 @@ void arch_init_copy_chip_data(struct irq old_cfg = get_irq_desc_chip_data(old_desc); - memcpy(cfg, old_cfg, sizeof(struct irq_cfg)); + cfg->vector = old_cfg->vector; + cfg->move_in_progress = old_cfg->move_in_progress; + cpumask_copy(cfg->domain, old_cfg->domain); + cpumask_copy(cfg->old_domain, old_cfg->old_domain); init_copy_irq_2_pin(old_cfg, cfg, node); } -static void free_irq_cfg(struct irq_cfg *old_cfg) +static void free_irq_cfg(struct irq_cfg *cfg) { - kfree(old_cfg); + free_cpumask_var(cfg->domain); + free_cpumask_var(cfg->old_domain); + kfree(cfg); } void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc)