public inbox for linux-mm@kvack.org
 help / color / mirror / Atom feed
* [PATCH mm-hotfixes 1/2] mm/page_alloc: return NULL early from alloc_frozen_pages_nolock() in NMI on UP
       [not found] <20260427054205.560734-1-harry@kernel.org>
@ 2026-04-27  5:42 ` Harry Yoo (Oracle)
  0 siblings, 0 replies; 4+ messages in thread
From: Harry Yoo (Oracle) @ 2026-04-27  5:42 UTC (permalink / raw)
  To: Andrew Morton, Vlastimil Babka, Shakeel Butt, Alexei Starovoitov,
	Harry Yoo
  Cc: Harry Yoo, Suren Baghdasaryan, Michal Hocko, Brendan Jackman,
	Johannes Weiner, Zi Yan, linux-mm, linux-kernel

On UP kernels (!CONFIG_SMP), spin_trylock() is a no-op that
unconditionally succeeds even when the lock is already held. As a
result, alloc_frozen_pages_nolock() called from NMI context can
re-enter rmqueue() and acquire the zone lock that the interrupted
context is already holding, corrupting the freelists.

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:
   <NMI>
   dump_stack_lvl+0x3f/0x60
   do_raw_spin_trylock+0x41/0x50
   _raw_spin_trylock+0x24/0x50
   rmqueue.isra.0+0x2a9/0xa70
   get_page_from_freelist+0xeb/0x450
   alloc_frozen_pages_nolock_noprof+0x111/0x1e0
   allocate_slab+0x42a/0x500
   ___slab_alloc+0xa7/0x4c0
   kmalloc_nolock_noprof+0x164/0x310
   [...]
   </NMI>

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

Link: https://lore.kernel.org/linux-mm/ad_cqe51pvr1WaDg@hyeyoo
Fixes: d7242af86434 ("mm: Introduce alloc_frozen_pages_nolock()")
Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
---
 mm/page_alloc.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 71859993dd54..23c7298d3be2 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -7737,6 +7737,11 @@ struct page *alloc_frozen_pages_nolock_noprof(gfp_t gfp_flags, int nid, unsigned
 	 */
 	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;
+
 	if (!pcp_allowed_order(order))
 		return NULL;
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH mm-hotfixes 1/2] mm/page_alloc: return NULL early from alloc_frozen_pages_nolock() in NMI on UP
       [not found] <20260427054736.566559-1-harry@kernel.org>
@ 2026-04-27  5:47 ` Harry Yoo (Oracle)
  2026-04-27  5:53   ` Harry Yoo (Oracle)
  2026-04-27  5:47 ` [PATCH mm-hotfixes 2/2] mm/slub: return NULL early from kmalloc_nolock() " Harry Yoo (Oracle)
  1 sibling, 1 reply; 4+ messages in thread
From: Harry Yoo (Oracle) @ 2026-04-27  5:47 UTC (permalink / raw)
  To: Andrew Morton, Vlastimil Babka, Alexei Starovoitov, Shakeel Butt,
	Harry Yoo
  Cc: Harry Yoo, Suren Baghdasaryan, Michal Hocko, Brendan Jackman,
	Johannes Weiner, Zi Yan, linux-mm, linux-kernel

On UP kernels (!CONFIG_SMP), spin_trylock() is a no-op that
unconditionally succeeds even when the lock is already held. As a
result, alloc_frozen_pages_nolock() called from NMI context can
re-enter rmqueue() and acquire the zone lock that the interrupted
context is already holding, corrupting the freelists.

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:
   <NMI>
   dump_stack_lvl+0x3f/0x60
   do_raw_spin_trylock+0x41/0x50
   _raw_spin_trylock+0x24/0x50
   rmqueue.isra.0+0x2a9/0xa70
   get_page_from_freelist+0xeb/0x450
   alloc_frozen_pages_nolock_noprof+0x111/0x1e0
   allocate_slab+0x42a/0x500
   ___slab_alloc+0xa7/0x4c0
   kmalloc_nolock_noprof+0x164/0x310
   [...]
   </NMI>

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

Link: https://lore.kernel.org/linux-mm/ad_cqe51pvr1WaDg@hyeyoo
Fixes: d7242af86434 ("mm: Introduce alloc_frozen_pages_nolock()")
Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
---
 mm/page_alloc.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 71859993dd54..23c7298d3be2 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -7737,6 +7737,11 @@ struct page *alloc_frozen_pages_nolock_noprof(gfp_t gfp_flags, int nid, unsigned
 	 */
 	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;
+
 	if (!pcp_allowed_order(order))
 		return NULL;
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH mm-hotfixes 2/2] mm/slub: return NULL early from kmalloc_nolock() in NMI on UP
       [not found] <20260427054736.566559-1-harry@kernel.org>
  2026-04-27  5:47 ` [PATCH mm-hotfixes 1/2] mm/page_alloc: return NULL early from alloc_frozen_pages_nolock() in NMI on UP Harry Yoo (Oracle)
@ 2026-04-27  5:47 ` Harry Yoo (Oracle)
  1 sibling, 0 replies; 4+ messages in thread
From: Harry Yoo (Oracle) @ 2026-04-27  5:47 UTC (permalink / raw)
  To: Vlastimil Babka, Harry Yoo, Andrew Morton, Alexei Starovoitov
  Cc: Harry Yoo, Hao Li, Christoph Lameter, David Rientjes,
	Roman Gushchin, linux-mm, linux-kernel

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 a 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:
   <NMI>
   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
   [...]
   </NMI>

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

Link: https://lore.kernel.org/linux-mm/ad_cqe51pvr1WaDg@hyeyoo
Fixes: af92793e52c3 ("slab: Introduce kmalloc_nolock() and kfree_nolock().")
Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
---
 mm/slub.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/mm/slub.c b/mm/slub.c
index 92362eeb13e5..b4ec15df92f6 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;
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH mm-hotfixes 1/2] mm/page_alloc: return NULL early from alloc_frozen_pages_nolock() in NMI on UP
  2026-04-27  5:47 ` [PATCH mm-hotfixes 1/2] mm/page_alloc: return NULL early from alloc_frozen_pages_nolock() in NMI on UP Harry Yoo (Oracle)
@ 2026-04-27  5:53   ` Harry Yoo (Oracle)
  0 siblings, 0 replies; 4+ messages in thread
From: Harry Yoo (Oracle) @ 2026-04-27  5:53 UTC (permalink / raw)
  To: Andrew Morton, Vlastimil Babka, Alexei Starovoitov, Shakeel Butt
  Cc: Suren Baghdasaryan, Michal Hocko, Brendan Jackman,
	Johannes Weiner, Zi Yan, linux-mm, linux-kernel

Apologies, I meant to run git sendmail --dry-run but messed it up
and sent V1 twice :/ (w/o cover letter). To avoid confusion, I will
send V2 with the cover letter. (Also I realize that I didn't add Cc:
stable on each patch, so will address that as well.)

On Mon, Apr 27, 2026 at 02:47:34PM +0900, Harry Yoo (Oracle) wrote:
> On UP kernels (!CONFIG_SMP), spin_trylock() is a no-op that
> unconditionally succeeds even when the lock is already held. As a
> result, alloc_frozen_pages_nolock() called from NMI context can
> re-enter rmqueue() and acquire the zone lock that the interrupted
> context is already holding, corrupting the freelists.
> 
> 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:
>    <NMI>
>    dump_stack_lvl+0x3f/0x60
>    do_raw_spin_trylock+0x41/0x50
>    _raw_spin_trylock+0x24/0x50
>    rmqueue.isra.0+0x2a9/0xa70
>    get_page_from_freelist+0xeb/0x450
>    alloc_frozen_pages_nolock_noprof+0x111/0x1e0
>    allocate_slab+0x42a/0x500
>    ___slab_alloc+0xa7/0x4c0
>    kmalloc_nolock_noprof+0x164/0x310
>    [...]
>    </NMI>
> 
> Fix this by returning NULL early when invoked from NMI on a UP kernel.
> 
> Link: https://lore.kernel.org/linux-mm/ad_cqe51pvr1WaDg@hyeyoo
> Fixes: d7242af86434 ("mm: Introduce alloc_frozen_pages_nolock()")
> Signed-off-by: Harry Yoo (Oracle) <harry@kernel.org>
> ---
>  mm/page_alloc.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index 71859993dd54..23c7298d3be2 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -7737,6 +7737,11 @@ struct page *alloc_frozen_pages_nolock_noprof(gfp_t gfp_flags, int nid, unsigned
>  	 */
>  	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;
> +
>  	if (!pcp_allowed_order(order))
>  		return NULL;
>  
> -- 
> 2.43.0
> 

-- 
Cheers,
Harry / Hyeonggon


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-04-27  5:53 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20260427054736.566559-1-harry@kernel.org>
2026-04-27  5:47 ` [PATCH mm-hotfixes 1/2] mm/page_alloc: return NULL early from alloc_frozen_pages_nolock() in NMI on UP Harry Yoo (Oracle)
2026-04-27  5:53   ` Harry Yoo (Oracle)
2026-04-27  5:47 ` [PATCH mm-hotfixes 2/2] mm/slub: return NULL early from kmalloc_nolock() " Harry Yoo (Oracle)
     [not found] <20260427054205.560734-1-harry@kernel.org>
2026-04-27  5:42 ` [PATCH mm-hotfixes 1/2] mm/page_alloc: return NULL early from alloc_frozen_pages_nolock() " Harry Yoo (Oracle)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox