powerpc/xive: propagate IPI init errors to prevent use-after-free

When xive_init_ipis() fails (e.g. irq_domain_alloc_irqs() fails),
the error path frees the global xive_ipis array.  However,
xive_smp_probe() previously ignored this failure and proceeded to
call xive_setup_cpu_ipi(), which dereferences the already-freed
xive_ipis pointer -- a use-after-free.

Now that xive_smp_probe() returns int (previous patch), propagate
the error from xive_init_ipis() and xive_setup_cpu_ipi() through
xive_smp_probe().  Check the return value in both pnv_smp_probe()
and pSeries_smp_probe() so that IPI setup is aborted cleanly on
failure, avoiding the use-after-free.

Fixes: 243e25112d ("powerpc/xive: Native exploitation of the XIVE interrupt controller")
Fixes: cbc06f051c ("powerpc/xive: Do not skip CPU-less nodes when creating the IPIs")
Signed-off-by: Gou Hao <gouhao@uniontech.com>
Reviewed-by: Wentao Guan <guanwentao@uniontech.com>
Reviewed-by: jiazhenyuan <jiazhenyuan@uniontech.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20260727104215.184786-4-gouhao@uniontech.com
This commit is contained in:
Gou Hao 2026-07-27 18:42:13 +08:00 committed by Madhavan Srinivasan
parent ab5ae5dceb
commit 411a3c016e
3 changed files with 16 additions and 10 deletions

View File

@ -332,10 +332,12 @@ static void pnv_cause_ipi(int cpu)
static void __init pnv_smp_probe(void)
{
if (xive_enabled())
xive_smp_probe();
else
if (xive_enabled()) {
if (xive_smp_probe() < 0)
return;
} else {
xics_smp_probe();
}
if (cpu_has_feature(CPU_FTR_DBELL)) {
ic_cause_ipi = smp_ops->cause_ipi;

View File

@ -194,10 +194,12 @@ static int pseries_cause_nmi_ipi(int cpu)
static __init void pSeries_smp_probe(void)
{
if (xive_enabled())
xive_smp_probe();
else
if (xive_enabled()) {
if (xive_smp_probe() < 0)
return;
} else {
xics_smp_probe();
}
/* No doorbell facility, must use the interrupt controller for IPIs */
if (!cpu_has_feature(CPU_FTR_DBELL))

View File

@ -1267,15 +1267,17 @@ noinstr static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc)
int __init xive_smp_probe(void)
{
int ret;
smp_ops->cause_ipi = xive_cause_ipi;
/* Register the IPI */
xive_init_ipis();
ret = xive_init_ipis();
if (ret < 0)
return ret;
/* Allocate and setup IPI for the boot CPU */
xive_setup_cpu_ipi(smp_processor_id());
return 0;
return xive_setup_cpu_ipi(smp_processor_id());
}
#endif /* CONFIG_SMP */