Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Shakeel Butt" <shakeel.butt@linux.dev>,
	"Andrew Morton" <akpm@linux-foundation.org>
Cc: "Dave Chinner" <david@fromorbit.com>,
	"Johannes Weiner" <hannes@cmpxchg.org>,
	"David Hildenbrand" <david@kernel.org>,
	"Michal Hocko" <mhocko@kernel.org>,
	"Roman Gushchin" <roman.gushchin@linux.dev>,
	"Muchun Song" <muchun.song@linux.dev>,
	"Qi Zheng" <qi.zheng@linux.dev>,
	"Meta kernel team" <kernel-team@meta.com>,
	linux-mm@kvack.org, "Chris Mason" <mason@kernel.org>
Subject: Re: [PATCH] mm: list_lru: fix NULL deref when a folio moves to the root memcg
Date: Fri, 13 Nov 2026 02:42:10 +0000	[thread overview]
Message-ID: <sashiko-outbox-212084@kernel.org> (raw)
In-Reply-To: <20261112024140.648088-1-shakeel.butt@linux.dev>

Thank you for your contribution! Sashiko AI review found no new issues
in this patch, but noticed 1 related pre-existing issue it does not
introduce:
- [High] mm/list_lru: infinite loop in __memcg_list_lru_alloc() on
  xas_nomem() failure [1]
--

commit 17fdd494fc11d51fee607883de9cf2593b4f8f83
Author: Shakeel Butt <shakeel.butt@linux.dev>

mm: list_lru: fix NULL deref when a folio moves to the root memcg

This commit skips calling __memcg_list_lru_alloc() in the slow path of
folio_memcg_list_lru_alloc() if the folio's memcg has been reparented to the
root memcg.

> diff --git a/mm/list_lru.c b/mm/list_lru.c
> index d1d256822ccc7..566691ca3dd8f 100644
> --- a/mm/list_lru.c
> +++ b/mm/list_lru.c
> @@ -645,9 +645,15 @@ int folio_memcg_list_lru_alloc(struct folio *folio, struct list_lru *lru,
>  	if (likely(res))
>  		return 0;
>  
> -	/* Allocation may block, pin the memcg */
> +	/*
> +	 * Allocation may block, so pin the memcg. If the folio's cgroup
> +	 * was removed after the check above, the folio has moved up to a
> +	 * parent memcg, which can be the root. The root uses the global
> +	 * lists and has no parent, so skip it.
> +	 */
>  	memcg = get_mem_cgroup_from_folio(folio);
> -	res = __memcg_list_lru_alloc(memcg, lru, gfp);
> +	if (!mem_cgroup_is_root(memcg))
> +		res = __memcg_list_lru_alloc(memcg, lru, gfp);
>  	mem_cgroup_put(memcg);
>  	return res;
>  }

[Severity: High]
This problem wasn't introduced by this patch, but can __memcg_list_lru_alloc()
enter an infinite loop [1] when xas_nomem() fails while populating an
ancestor cgroup?

mm/list_lru.c:__memcg_list_lru_alloc() {
	...
	do {
		pos = memcg;
		parent = parent_mem_cgroup(pos);
		while (!memcg_list_lru_allocated(parent, lru)) {
			pos = parent;
			parent = parent_mem_cgroup(pos);
		}
		...
		xas_set(&xas, pos->kmemcg_id);
		do {
			xas_lock_irqsave(&xas, flags);
			if (!xas_load(&xas) && !css_is_dying(&pos->css)) {
				xas_store(&xas, mlru);
				if (!xas_error(&xas))
					mlru = NULL;
			}
			xas_unlock_irqrestore(&xas, flags);
		} while (xas_nomem(&xas, gfp));
	} while (pos != memcg && !css_is_dying(&pos->css));
	...
	return xas_error(&xas);
}

When storing mlru for an ancestor (pos != memcg) needs a new xa_node,
xas_store() sets xas to -ENOMEM and leaves pos unpopulated in lru->xa.  If
xas_nomem() then fails to allocate a node (for example under memory pressure,
or when gfp &= GFP_RECLAIM_MASK strips GFP_NOWAIT), it returns false with xas
still in the error state.

Because the outer loop does not check !xas_error(&xas), it repeats for the
same unpopulated ancestor pos, where xas_set() resets xas.xa_node to
XAS_RESTART and clears the error, looping forever and causing a soft or hard
lockup.

[1] https://sashiko.dev/#/bug/linux-21c1dba9-8d6f-4368-b38b-9a57cacb056f

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261112024140.648088-1-shakeel.butt@linux.dev?part=1


      parent reply	other threads:[~2026-11-13  2:42 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-12  2:41 [PATCH] mm: list_lru: fix NULL deref when a folio moves to the root memcg Shakeel Butt
2026-11-12  2:49 ` Muchun Song
2026-11-12  5:44   ` Shakeel Butt
2026-11-13  2:42 ` sashiko-bot [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-212084@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=david@fromorbit.com \
    --cc=david@kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=kernel-team@meta.com \
    --cc=linux-mm@kvack.org \
    --cc=mason@kernel.org \
    --cc=mhocko@kernel.org \
    --cc=muchun.song@linux.dev \
    --cc=qi.zheng@linux.dev \
    --cc=roman.gushchin@linux.dev \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=shakeel.butt@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox