{"vulnerability": "CVE-2026-98395", "sightings": [{"uuid": "d0540ed8-b151-4836-b453-5691551e8183", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-98395", "type": "seen", "source": "https://infosec.exchange/users/cve/statuses/117440677560723706", "content": "CVE-2026-98395 powerpc/entry: Fix irq_soft_mask corruption on replayed interrupt exit In the Linux kernel, the following vulnerability has been resolved:\npowerpc/entry: Fix irq_soft_mask corruption on replayed interrupt exit\nWhen __replay_soft_interrupts() replays a pending interrupt (e.g.PACA_IRQ_DEC -&gt; timer_interrupt), it calls the handler directly with asynthetic pt_regs. The DEFINE_INTERRUPT_HANDLER_ASYNC wrapper aroundeach handler calls arch_interrupt_async_exit_prepare() on the way out,which calls arch_interrupt_exit_prepare() -&gt; local_irq_disable() -&gt;arch_local_irq_disable(), which does:\n    irq_soft_mask_set(IRQS_DISABLED)   /* 0x1 */\nThis unconditionally overwrites irq_soft_mask with IRQS_DISABLED (0x1),stripping the IRQS_PMI_DISABLED (0x2) bit. The result is thatirq_soft_mask is 0x1 instead of IRQS_ALL_DISABLED (0x3) when thehandler returns to __replay_soft_interrupts().\nFor a normally-taken interrupt this is harmless: the next interruptalways enters through arch_interrupt_enter_prepare() whichunconditionally sets irq_soft_mask to IRQS_ALL_DISABLED. But duringreplay, next_interrupt() is called directly between replayed handlerswithout going back through arch_interrupt_enter_prepare(), so thestripped bit is never restored. next_interrupt() then fires a WARNING:\n    WARNING: arch/powerpc/kernel/irq_64.c:75    WARN_ON(irq_soft_mask_return() != IRQS_ALL_DISABLED)\nThe warning was observed early in boot on a POWER10 pseries guestduring kmem_cache_init_late(), where a spinlock release triggersinterrupt replay that processes a pending timer interrupt.\nDebugger state confirming the bug:  Before timer_interrupt(&amp;regs):    irq_soft_mask = 0x3 (IRQS_ALL_DISABLED)   correct    irq_happened  = 0x41 (HARD_DIS|REPLAYING)  correct  After timer_interrupt(&amp;regs) returns:    irq_soft_mask = 0x1 (IRQS_DISABLED)        WRONG - PMI bit stripped    irq_happened  = 0x41                        unchanged\nThe fix is to replace local_irq_disable() with hard_irq_disable().\nhard_irq_disable() is the right primitive here for two reasons:\n1. 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.\n2. On PPC32 (hw_irq.h:467) hard_irq_disable() maps to   arch_local_irq_disable() -&gt; __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:\n       arch/powerpc/include/asm/entry-common.h:273: error: implicit       declaration of function 'irq_soft_mask_set'\n   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.\nhttps://www.cve.org/CVERecord?id=CVE-2026-98395https://git.kernel.org/stable/c/95cd316a896f1c1aa4ee4a817ba3d4691103c81bhttps://git.kernel.org/stable/c/63a7531ca31f9f097d9cc1cc3fe86ae683cdabdd#kernel #Linux#CVE_2026_98395#bot", "creation_timestamp": "2026-10-14T18:28:46.877221Z"}]}