powerpc/entry: Fix irq_soft_mask corruption on replayed interrupt exit
Summary
| CVE | CVE-2026-98395 |
| State | PUBLISHED |
| Assigner | Linux |
| Source Priority | CVE Program / NVD first with legacy fallback |
| Published | 2026-10-14 14:17:50 UTC |
| Updated | 2026-10-19 10:18:42 UTC |
| Description | In the Linux kernel, the following vulnerability has been resolved:
powerpc/entry: Fix irq_soft_mask corruption on replayed interrupt exit
When __replay_soft_interrupts() replays a pending interrupt (e.g.
PACA_IRQ_DEC -> timer_interrupt), it calls the handler directly with a
synthetic pt_regs. The DEFINE_INTERRUPT_HANDLER_ASYNC wrapper around
each handler calls arch_interrupt_async_exit_prepare() on the way out,
which calls arch_interrupt_exit_prepare() -> local_irq_disable() ->
arch_local_irq_disable(), which does:
irq_soft_mask_set(IRQS_DISABLED) /* 0x1 */
This unconditionally overwrites irq_soft_mask with IRQS_DISABLED (0x1),
stripping the IRQS_PMI_DISABLED (0x2) bit. The result is that
irq_soft_mask is 0x1 instead of IRQS_ALL_DISABLED (0x3) when the
handler returns to __replay_soft_interrupts().
For a normally-taken interrupt this is harmless: the next interrupt
always enters through arch_interrupt_enter_prepare() which
unconditionally sets irq_soft_mask to IRQS_ALL_DISABLED. But during
replay, next_interrupt() is called directly between replayed handlers
without going back through arch_interrupt_enter_prepare(), so the
stripped bit is never restored. next_interrupt() then fires a WARNING:
WARNING: arch/powerpc/kernel/irq_64.c:75
WARN_ON(irq_soft_mask_return() != IRQS_ALL_DISABLED)
The warning was observed early in boot on a POWER10 pseries guest
during kmem_cache_init_late(), where a spinlock release triggers
interrupt replay that processes a pending timer interrupt.
Debugger state confirming the bug:
Before timer_interrupt(®s):
irq_soft_mask = 0x3 (IRQS_ALL_DISABLED) correct
irq_happened = 0x41 (HARD_DIS|REPLAYING) correct
After timer_interrupt(®s) returns:
irq_soft_mask = 0x1 (IRQS_DISABLED) WRONG - PMI bit stripped
irq_happened = 0x41 unchanged
The fix is to replace local_irq_disable() with hard_irq_disable().
hard_irq_disable() is the right primitive here for two reasons:
1. On PPC64 (hw_irq.h:301) it calls irq_soft_mask_set_return(IRQS_ALL_DISABLED),
setting the soft mask to 0x3 (both IRQS_DISABLED and IRQS_PMI_DISABLED),
which preserves the PMI bit and fixes the WARNING. The additional
work it does (__hard_irq_disable(), PACA_IRQ_HARD_DIS |=) is
redundant but safe since both are already set at this point in the
exit path; the trace_hardirqs_off() inside is guarded by
if (!arch_irqs_disabled_flags(flags)) so it will not double-fire.
2. On PPC32 (hw_irq.h:467) hard_irq_disable() maps to
arch_local_irq_disable() -> __hard_irq_disable(), which clears
MSR[EE] in hardware. This is exactly correct: PPC32 has no soft-mask
PACA mechanism, so the hardware disable is the right way to satisfy
irqentry_exit()'s requirement. This also fixes a build error on PPC32
where irq_soft_mask_set() is only defined under CONFIG_PPC64:
arch/powerpc/include/asm/entry-common.h:273: error: implicit
declaration of function 'irq_soft_mask_set'
Using hard_irq_disable() requires no #ifdef and is consistent with
how the rest of the entry code (e.g. entry-common.h:463) handles the
same PPC32/PPC64 split. |
Vendor Declared Affected Products
| Source | Vendor | Product | Version | Platforms |
|---|
| CNA |
Linux |
Linux |
affected 334f3f6d7a1660fd65597bad9960bfa33a716d35 95cd316a896f1c1aa4ee4a817ba3d4691103c81b git |
Not specified |
| CNA |
Linux |
Linux |
affected 334f3f6d7a1660fd65597bad9960bfa33a716d35 63a7531ca31f9f097d9cc1cc3fe86ae683cdabdd git |
Not specified |
| CNA |
Linux |
Linux |
affected 7.2 |
Not specified |
| CNA |
Linux |
Linux |
unaffected 7.2 semver |
Not specified |
| CNA |
Linux |
Linux |
unaffected 7.2.7 7.2.* semver |
Not specified |
| CNA |
Linux |
Linux |
unaffected 7.3 * original_commit_for_fix |
Not specified |
References
| Reference | Source | Link | Tags |
|---|
| git.kernel.org/stable/c/63a7531ca31f9f097d9cc1cc3fe86ae683cdabdd |
416baaa9-dc9f-4396-8d5f-8c081fb06d67 |
git.kernel.org |
|
| git.kernel.org/stable/c/95cd316a896f1c1aa4ee4a817ba3d4691103c81b |
416baaa9-dc9f-4396-8d5f-8c081fb06d67 |
git.kernel.org |
|
| CVE Program record |
CVE.ORG |
www.cve.org |
canonical |
| NVD vulnerability detail |
NVD |
nvd.nist.gov |
canonical, analysis |
No vendor comments have been submitted for this CVE.
There are currently no legacy QID mappings associated with this CVE.