[PATCH v2 3/3] powerpc/xive: Extra sanity checks on cpu numbers

Benjamin Herrenschmidt benh at kernel.crashing.org
Mon Apr 10 16:30:01 AEST 2017


When targetting interrupts we do various manipulations of cpu numbers
and CPU masks. This adds some sanity checking to ensure we don't
break assumptions and manpulate cpu numbers that are out of bounds
of the various cpumasks.

Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
 arch/powerpc/sysdev/xive/common.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c
index f37d257..f78a779 100644
--- a/arch/powerpc/sysdev/xive/common.c
+++ b/arch/powerpc/sysdev/xive/common.c
@@ -421,8 +421,10 @@ static void xive_dec_target_count(int cpu)
 	struct xive_cpu *xc = per_cpu(xive_cpu, cpu);
 	struct xive_q *q = &xc->queue[xive_irq_priority];
 
-	if (WARN_ON(cpu < 0))
+	if (unlikely(WARN_ON(cpu < 0 || !xc))) {
+		pr_err("%s: cpu=%d xc=%p\n", __func__, cpu, xc);
 		return;
+	}
 
 	/*
 	 * We increment the "pending count" which will be used
@@ -446,8 +448,14 @@ static int xive_find_target_in_mask(const struct cpumask *mask,
 
 	/* Locate it */
 	cpu = cpumask_first(mask);
-	for (i = 0; i < first; i++)
+	for (i = 0; i < first && cpu < nr_cpu_ids; i++)
 		cpu = cpumask_next(cpu, mask);
+
+	/* Sanity check */
+	if (WARN_ON(cpu >= nr_cpu_ids))
+		cpu = cpumask_first(cpu_online_mask);
+
+	/* Remember first one to handle wrap-around */
 	first = cpu;
 
 	/*
@@ -540,6 +548,12 @@ static unsigned int xive_irq_startup(struct irq_data *d)
 		pr_warn("XIVE: irq %d started with broken affinity\n",
 			d->irq);
 	}
+
+	/* Sanity check */
+	if (WARN_ON(target == XIVE_INVALID_TARGET ||
+		    target >= nr_cpu_ids))
+		target = smp_processor_id();
+
 	xd->target = target;
 
 	/*
@@ -670,6 +684,10 @@ static int xive_irq_set_affinity(struct irq_data *d,
 	if (target == XIVE_INVALID_TARGET)
 		return -ENXIO;
 
+	/* Sanity check */
+	if (WARN_ON(target >= nr_cpu_ids))
+		target = smp_processor_id();
+
 	old_target = xd->target;
 
 	/*
-- 
2.9.3



More information about the Linuxppc-dev mailing list