VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-46029

CVE-2026-46029

Description

In the Linux kernel, the following vulnerability has been resolved:

mm/slab: return NULL early from kmalloc_nolock() in NMI on UP

On UP kernels (!CONFIG_SMP), spin_trylock() is a no-op that unconditionally succeeds even when the lock is already held. As a result, kmalloc_nolock() called from NMI context can re-enter the slab allocator and acquire n->list_lock that the interrupted context is already holding, corrupting slab state.

With CONFIG_DEBUG_SPINLOCK on UP, the following BUG is triggered with the slub_kunit test module:

BUG: spinlock trylock failure on UP on CPU#0, kunit_try_catch/243 [...] Call Trace:

dump_stack_lvl+0x3f/0x60 do_raw_spin_trylock+0x41/0x50 _raw_spin_trylock+0x24/0x50 get_from_partial_node+0x120/0x4d0 ___slab_alloc+0x8a/0x4c0 kmalloc_nolock_noprof+0x164/0x310 [...]

Fix this by returning NULL early when invoked from NMI on a UP kernel.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

kmalloc_nolock() in the Linux kernel returns NULL early when called from NMI context on UP systems to prevent slab corruption from re-entering a held spinlock.

Vulnerability

In the Linux kernel, kmalloc_nolock() on UP kernels (!CONFIG_SMP) can be safely re-entered from NMI context because spin_trylock() is a no-op that always succeeds. This allows the function to acquire n->list_lock while the interrupted context already holds it, corrupting slab allocator state. The issue is demonstrated with CONFIG_DEBUG_SPINLOCK and the slub_kunit test module showing a BUG: spinlock trylock failure on UP trace [1].

Exploitation

An attacker capable of triggering an NMI (Non-Maskable Interrupt) on a UP kernel while kmalloc_nolock() is executing in the interrupted context can cause re-entry into the slab allocator. The NMI handler must call kmalloc_nolock() (or a function that calls it) to reach the vulnerable code path. No special authentication or network access is required, only the ability to raise an NMI, which typically requires local access or certain hardware events.

Impact

Successful exploitation corrupts slab internal state, leading to memory corruption, system crashes, or potential privilege escalation depending on the corrupted data structures. The vulnerability is primarily a denial-of-service risk (system instability, panic) but under controlled conditions could be leveraged for further compromise.

Mitigation

The fix has been applied in the Linux kernel commit 5b31044e649e3e54c2caef135c09b371c2fbcd08 [1]. The patch returns NULL early from kmalloc_nolock() when called from NMI context on UP kernels. Users should update to a kernel version containing this commit or backport the fix. No workaround is available for unpatched systems beyond avoiding NMI-triggering operations.

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

6
a8d95d274be2

mm/slab: return NULL early from kmalloc_nolock() in NMI on UP

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"Harry Yoo (Oracle)"Apr 27, 2026Fixed in 6.18.27via kernel-cna
1 file changed · +5 1
  • mm/slub.c+5 1 modified
    diff --git a/mm/slub.c b/mm/slub.c
    index 27aa0e2975a5f2..a89df6ddcc5874 100644
    --- a/mm/slub.c
    +++ b/mm/slub.c
    @@ -5752,6 +5752,11 @@ void *kmalloc_nolock_noprof(size_t size, gfp_t gfp_flags, int node)
     		 * sleeping lock on RT.
     		 */
     		return NULL;
    +
    +	/* On UP, spin_trylock() always succeeds even when it is locked */
    +	if (!IS_ENABLED(CONFIG_SMP) && in_nmi())
    +		return NULL;
    +
     retry:
     	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
     		return NULL;
    -- 
    cgit 1.3-korg
    
    
    
d66553204a15

mm/slab: return NULL early from kmalloc_nolock() in NMI on UP

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"Harry Yoo (Oracle)"Apr 27, 2026Fixed in 7.0.4via kernel-cna
1 file changed · +4 1
  • mm/slub.c+4 1 modified
    diff --git a/mm/slub.c b/mm/slub.c
    index 90af21126921d0..e423afa27d1a46 100644
    --- a/mm/slub.c
    +++ b/mm/slub.c
    @@ -5304,6 +5304,10 @@ void *kmalloc_nolock_noprof(size_t size, gfp_t gfp_flags, int node)
     	if (IS_ENABLED(CONFIG_PREEMPT_RT) && (in_nmi() || in_hardirq()))
     		return NULL;
     
    +	/* On UP, spin_trylock() always succeeds even when it is locked */
    +	if (!IS_ENABLED(CONFIG_SMP) && in_nmi())
    +		return NULL;
    +
     retry:
     	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
     		return NULL;
    -- 
    cgit 1.3-korg
    
    
    
5b31044e649e

mm/slab: return NULL early from kmalloc_nolock() in NMI on UP

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"Harry Yoo (Oracle)"Apr 27, 2026Fixed in 7.1-rc2via kernel-cna
1 file changed · +4 1
  • mm/slub.c+4 1 modified
    diff --git a/mm/slub.c b/mm/slub.c
    index 161079ac5ba128..0baa906f39ab84 100644
    --- a/mm/slub.c
    +++ b/mm/slub.c
    @@ -5339,6 +5339,10 @@ void *kmalloc_nolock_noprof(size_t size, gfp_t gfp_flags, int node)
     	if (IS_ENABLED(CONFIG_PREEMPT_RT) && (in_nmi() || in_hardirq()))
     		return NULL;
     
    +	/* On UP, spin_trylock() always succeeds even when it is locked */
    +	if (!IS_ENABLED(CONFIG_SMP) && in_nmi())
    +		return NULL;
    +
     retry:
     	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
     		return NULL;
    -- 
    cgit 1.3-korg
    
    
    
a8d95d274be2

mm/slab: return NULL early from kmalloc_nolock() in NMI on UP

1 file changed · +5 1
  • mm/slub.c+5 1 modified
    diff --git a/mm/slub.c b/mm/slub.c
    index 27aa0e2975a5f2..a89df6ddcc5874 100644
    --- a/mm/slub.c
    +++ b/mm/slub.c
    @@ -5752,6 +5752,11 @@ void *kmalloc_nolock_noprof(size_t size, gfp_t gfp_flags, int node)
     		 * sleeping lock on RT.
     		 */
     		return NULL;
    +
    +	/* On UP, spin_trylock() always succeeds even when it is locked */
    +	if (!IS_ENABLED(CONFIG_SMP) && in_nmi())
    +		return NULL;
    +
     retry:
     	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
     		return NULL;
    -- 
    cgit 1.3-korg
    
    
    
d66553204a15

mm/slab: return NULL early from kmalloc_nolock() in NMI on UP

1 file changed · +4 1
  • mm/slub.c+4 1 modified
    diff --git a/mm/slub.c b/mm/slub.c
    index 90af21126921d0..e423afa27d1a46 100644
    --- a/mm/slub.c
    +++ b/mm/slub.c
    @@ -5304,6 +5304,10 @@ void *kmalloc_nolock_noprof(size_t size, gfp_t gfp_flags, int node)
     	if (IS_ENABLED(CONFIG_PREEMPT_RT) && (in_nmi() || in_hardirq()))
     		return NULL;
     
    +	/* On UP, spin_trylock() always succeeds even when it is locked */
    +	if (!IS_ENABLED(CONFIG_SMP) && in_nmi())
    +		return NULL;
    +
     retry:
     	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
     		return NULL;
    -- 
    cgit 1.3-korg
    
    
    
5b31044e649e

mm/slab: return NULL early from kmalloc_nolock() in NMI on UP

1 file changed · +4 1
  • mm/slub.c+4 1 modified
    diff --git a/mm/slub.c b/mm/slub.c
    index 161079ac5ba128..0baa906f39ab84 100644
    --- a/mm/slub.c
    +++ b/mm/slub.c
    @@ -5339,6 +5339,10 @@ void *kmalloc_nolock_noprof(size_t size, gfp_t gfp_flags, int node)
     	if (IS_ENABLED(CONFIG_PREEMPT_RT) && (in_nmi() || in_hardirq()))
     		return NULL;
     
    +	/* On UP, spin_trylock() always succeeds even when it is locked */
    +	if (!IS_ENABLED(CONFIG_SMP) && in_nmi())
    +		return NULL;
    +
     retry:
     	if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
     		return NULL;
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"On UP kernels, spin_trylock() is a no-op that unconditionally succeeds even when the lock is already held, allowing kmalloc_nolock() called from NMI context to re-enter the slab allocator and acquire n->list_lock that the interrupted context is already holding."

Attack vector

An attacker who can trigger an NMI (Non-Maskable Interrupt) on a UP (!CONFIG_SMP) kernel can cause kmalloc_nolock() to be invoked while the interrupted context already holds n->list_lock. Because spin_trylock() on UP unconditionally succeeds, the NMI handler re-enters the slab allocator and corrupts slab state. The bug is demonstrated by the slub_kunit test module, which triggers the NMI code path and produces a spinlock trylock failure BUG under CONFIG_DEBUG_SPINLOCK [patch_id=2660299].

Affected code

The vulnerable code is in the function kmalloc_nolock_noprof() in mm/slub.c [patch_id=2660299]. The function previously only guarded against NMI re-entry on PREEMPT_RT kernels, but lacked a check for UP (!CONFIG_SMP) kernels where spin_trylock() is a no-op.

What the fix does

The patch adds an early return of NULL at the top of kmalloc_nolock_noprof() when the kernel is compiled without CONFIG_SMP and the call originates from NMI context [patch_id=2660299]. This prevents the re-entrant slab allocation that would otherwise corrupt slab state. The existing PREEMPT_RT guard already returned NULL for NMI/hardirq on RT kernels; the new check handles the UP case where spin_trylock provides no actual locking.

Preconditions

  • configKernel must be compiled without CONFIG_SMP (UP kernel)
  • inputkmalloc_nolock() must be called from NMI context

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

3

News mentions

0

No linked articles in our index yet.