Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec882542 authored by Xiu Jianfeng's avatar Xiu Jianfeng Committed by Greg Kroah-Hartman
Browse files

x86/xen: Fix memory leak in xen_smp_intr_init{_pv}()



[ Upstream commit 69143f60868b3939ddc89289b29db593b647295e ]

These local variables @{resched|pmu|callfunc...}_name saves the new
string allocated by kasprintf(), and when bind_{v}ipi_to_irqhandler()
fails, it goes to the @fail tag, and calls xen_smp_intr_free{_pv}() to
free resource, however the new string is not saved, which cause a memory
leak issue. fix it.

Fixes: 9702785a ("i386: move xen")
Signed-off-by: default avatarXiu Jianfeng <xiujianfeng@huawei.com>
Reviewed-by: default avatarJuergen Gross <jgross@suse.com>
Link: https://lore.kernel.org/r/20221123155858.11382-2-xiujianfeng@huawei.com


Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 6e98158d
Loading
Loading
Loading
Loading
+12 −12
Original line number Diff line number Diff line
@@ -32,30 +32,30 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id)

void xen_smp_intr_free(unsigned int cpu)
{
	kfree(per_cpu(xen_resched_irq, cpu).name);
	per_cpu(xen_resched_irq, cpu).name = NULL;
	if (per_cpu(xen_resched_irq, cpu).irq >= 0) {
		unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu).irq, NULL);
		per_cpu(xen_resched_irq, cpu).irq = -1;
		kfree(per_cpu(xen_resched_irq, cpu).name);
		per_cpu(xen_resched_irq, cpu).name = NULL;
	}
	kfree(per_cpu(xen_callfunc_irq, cpu).name);
	per_cpu(xen_callfunc_irq, cpu).name = NULL;
	if (per_cpu(xen_callfunc_irq, cpu).irq >= 0) {
		unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu).irq, NULL);
		per_cpu(xen_callfunc_irq, cpu).irq = -1;
		kfree(per_cpu(xen_callfunc_irq, cpu).name);
		per_cpu(xen_callfunc_irq, cpu).name = NULL;
	}
	kfree(per_cpu(xen_debug_irq, cpu).name);
	per_cpu(xen_debug_irq, cpu).name = NULL;
	if (per_cpu(xen_debug_irq, cpu).irq >= 0) {
		unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu).irq, NULL);
		per_cpu(xen_debug_irq, cpu).irq = -1;
		kfree(per_cpu(xen_debug_irq, cpu).name);
		per_cpu(xen_debug_irq, cpu).name = NULL;
	}
	kfree(per_cpu(xen_callfuncsingle_irq, cpu).name);
	per_cpu(xen_callfuncsingle_irq, cpu).name = NULL;
	if (per_cpu(xen_callfuncsingle_irq, cpu).irq >= 0) {
		unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu).irq,
				       NULL);
		per_cpu(xen_callfuncsingle_irq, cpu).irq = -1;
		kfree(per_cpu(xen_callfuncsingle_irq, cpu).name);
		per_cpu(xen_callfuncsingle_irq, cpu).name = NULL;
	}
}

@@ -65,6 +65,7 @@ int xen_smp_intr_init(unsigned int cpu)
	char *resched_name, *callfunc_name, *debug_name;

	resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu);
	per_cpu(xen_resched_irq, cpu).name = resched_name;
	rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
				    cpu,
				    xen_reschedule_interrupt,
@@ -74,9 +75,9 @@ int xen_smp_intr_init(unsigned int cpu)
	if (rc < 0)
		goto fail;
	per_cpu(xen_resched_irq, cpu).irq = rc;
	per_cpu(xen_resched_irq, cpu).name = resched_name;

	callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu);
	per_cpu(xen_callfunc_irq, cpu).name = callfunc_name;
	rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR,
				    cpu,
				    xen_call_function_interrupt,
@@ -86,10 +87,10 @@ int xen_smp_intr_init(unsigned int cpu)
	if (rc < 0)
		goto fail;
	per_cpu(xen_callfunc_irq, cpu).irq = rc;
	per_cpu(xen_callfunc_irq, cpu).name = callfunc_name;

	if (!xen_fifo_events) {
		debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
		per_cpu(xen_debug_irq, cpu).name = debug_name;
		rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu,
					     xen_debug_interrupt,
					     IRQF_PERCPU | IRQF_NOBALANCING,
@@ -97,10 +98,10 @@ int xen_smp_intr_init(unsigned int cpu)
		if (rc < 0)
			goto fail;
		per_cpu(xen_debug_irq, cpu).irq = rc;
		per_cpu(xen_debug_irq, cpu).name = debug_name;
	}

	callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu);
	per_cpu(xen_callfuncsingle_irq, cpu).name = callfunc_name;
	rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR,
				    cpu,
				    xen_call_function_single_interrupt,
@@ -110,7 +111,6 @@ int xen_smp_intr_init(unsigned int cpu)
	if (rc < 0)
		goto fail;
	per_cpu(xen_callfuncsingle_irq, cpu).irq = rc;
	per_cpu(xen_callfuncsingle_irq, cpu).name = callfunc_name;

	return 0;

+6 −6
Original line number Diff line number Diff line
@@ -98,18 +98,18 @@ asmlinkage __visible void cpu_bringup_and_idle(void)

void xen_smp_intr_free_pv(unsigned int cpu)
{
	kfree(per_cpu(xen_irq_work, cpu).name);
	per_cpu(xen_irq_work, cpu).name = NULL;
	if (per_cpu(xen_irq_work, cpu).irq >= 0) {
		unbind_from_irqhandler(per_cpu(xen_irq_work, cpu).irq, NULL);
		per_cpu(xen_irq_work, cpu).irq = -1;
		kfree(per_cpu(xen_irq_work, cpu).name);
		per_cpu(xen_irq_work, cpu).name = NULL;
	}

	kfree(per_cpu(xen_pmu_irq, cpu).name);
	per_cpu(xen_pmu_irq, cpu).name = NULL;
	if (per_cpu(xen_pmu_irq, cpu).irq >= 0) {
		unbind_from_irqhandler(per_cpu(xen_pmu_irq, cpu).irq, NULL);
		per_cpu(xen_pmu_irq, cpu).irq = -1;
		kfree(per_cpu(xen_pmu_irq, cpu).name);
		per_cpu(xen_pmu_irq, cpu).name = NULL;
	}
}

@@ -119,6 +119,7 @@ int xen_smp_intr_init_pv(unsigned int cpu)
	char *callfunc_name, *pmu_name;

	callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
	per_cpu(xen_irq_work, cpu).name = callfunc_name;
	rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
				    cpu,
				    xen_irq_work_interrupt,
@@ -128,10 +129,10 @@ int xen_smp_intr_init_pv(unsigned int cpu)
	if (rc < 0)
		goto fail;
	per_cpu(xen_irq_work, cpu).irq = rc;
	per_cpu(xen_irq_work, cpu).name = callfunc_name;

	if (is_xen_pmu) {
		pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu);
		per_cpu(xen_pmu_irq, cpu).name = pmu_name;
		rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu,
					     xen_pmu_irq_handler,
					     IRQF_PERCPU|IRQF_NOBALANCING,
@@ -139,7 +140,6 @@ int xen_smp_intr_init_pv(unsigned int cpu)
		if (rc < 0)
			goto fail;
		per_cpu(xen_pmu_irq, cpu).irq = rc;
		per_cpu(xen_pmu_irq, cpu).name = pmu_name;
	}

	return 0;