PT-2026-114374 · Linux · Linux

CVE-2026-98395

·

Published

2026-10-14

·

Updated

2026-10-14

None

No severity ratings or metrics are available. When they are, we'll update the corresponding info on the page.
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(&regs): irq soft mask = 0x3 (IRQS ALL DISABLED) correct irq happened = 0x41 (HARD DIS|REPLAYING) correct After timer interrupt(&regs) 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.
Found an issue in the description? Have something to add? Feel free to write us 👾

Related Identifiers

CVE-2026-98395

Affected Products

Linux