CVE-2026-98395

CVE-2026-98395

published October 14, 2026

CVSS
—
EPSS
0%
Percentile
9.0
In the wild
Unconfirmed
What it is

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.

The record
Technical detail
CVSS
Not scored
CVSS v4.0
Not supplied
EPSS
0.00198 · 9.0th percentile
Published
2026-10-14T18:17Z
References (2)
EPSS history
Timeline
  • 16 OCT 03:33Z
    EPSS moved — → 0%
    epss
  • 14 OCT 13:25Z
    powerpc/entry: Fix irq_soft_mask corruption on replayed interrupt exit
    cvelistv5
  • 14 OCT 13:25Z
    powerpc/entry: Fix irq_soft_mask corruption on replayed interrupt exit
    cvelistv5