From: "Zi Yan" <ziy@nvidia.com>
To: "Vlastimil Babka (SUSE)" <vbabka@kernel.org>,
"Ye Liu" <ye.liu@linux.dev>
Cc: "Andrew Morton" <akpm@linux-foundation.org>,
"Suren Baghdasaryan" <surenb@google.com>,
"Michal Hocko" <mhocko@suse.com>,
"Brendan Jackman" <jackmanb@google.com>,
"Johannes Weiner" <hannes@cmpxchg.org>, <linux-mm@kvack.org>,
<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v5 9/9] mm/page_owner: use memcg_data snapshot instead of PageMemcgKmem() to avoid TOCTOU VM_BUG_ON
Date: Mon, 13 Jul 2026 15:27:34 -0400 [thread overview]
Message-ID: <DJXOW0P35L9B.395DKD4LXEA3R@nvidia.com> (raw)
In-Reply-To: <48dd2c46-bf55-44fe-b7e6-24037ba59aed@kernel.org>
On Mon Jul 13, 2026 at 1:34 PM EDT, Vlastimil Babka (SUSE) wrote:
> On 7/13/26 04:40, Ye Liu wrote:
>>
>>
>> 在 2026/7/10 23:56, Zi Yan 写道:
>>> On 10 Jul 2026, at 2:51, Ye Liu wrote:
>>>
>>>> 在 2026/7/2 10:02, Zi Yan 写道:
>>>>> On 1 Jul 2026, at 2:10, Ye Liu wrote:
>>>>>
>>>>>> print_page_owner_memcg() takes a snapshot of page->memcg_data via
>>>>>> READ_ONCE at the top of the function and guards against tail pages
>>>>>> and NULL memcg_data. However, at the end it calls PageMemcgKmem(page)
>>>>>> which internally calls folio_memcg_kmem() — and that function re-reads
>>>>>> folio->memcg_data and page->compound_head locklessly, wrapping both
>>>>>> in VM_BUG_ON assertions:
>>>>>>
>>>>>> VM_BUG_ON_PGFLAGS(PageTail(&folio->page), &folio->page);
>>>>>> VM_BUG_ON_FOLIO(folio->memcg_data & MEMCG_DATA_OBJEXTS, folio);
>>>>>>
>>>>>> If the page is concurrently freed and reallocated as a THP tail page
>>>>>> or a slab page between the initial guards and this final call, the
>>>>>> VM_BUG_ON assertions can fire on debug builds (CONFIG_DEBUG_VM=y),
>>>>>> causing a kernel panic.
>>>>>>
>>>>>> Fix by reusing the memcg_data snapshot already taken at function entry
>>>>>> instead of calling PageMemcgKmem(), which is semantically equivalent:
>>>>>> PageMemcgKmem()->folio_memcg_kmem()->folio->memcg_data & MEMCG_DATA_KMEM.
>>>>>> This avoids both the TOCTOU window and the assertions entirely.
>>>>>>
>>>>>> Signed-off-by: Ye Liu <ye.liu@linux.dev>
>>>>>> ---
>>>>>> mm/page_owner.c | 2 +-
>>>>>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>>>>>
>>>>> LGTM.
>>>>>
>>>>> Reviewed-by: Zi Yan <ziy@nvidia.com>Hi,Zi,Vlastimil
>>>>
>>>> This patch still has warnings (see sashiko link[1]).
>>>> I've made the following modifications, or do you have any better suggestions?
>>>
>>> Maybe use snapshot_page() from mm/debug.c, so that you do not need to replicate
>>> the code from folio_memcg_check(). You probably still need the rcu_read_lock()
>>> when reading memcg_data from the snapshot to prevent memcg going away.
>>>
>> But it does a full struct page + struct folio memcpy with retry loops,
>> which is more than what we need here -- we only care about memcg_data.
>
> Yeah seems too unnecessarily heavy.
>
>> The READ_ONCE() snapshot is sufficient since the function already
>> holds rcu_read_lock() to keep the memcg alive once resolved.
>>
>> The two-line inline of folio_memcg_check() logic is minimal, and we need
>> the OBJEXTS check to be explicit anyway (to print "Slab cache page\n"
>> -- page_memcg_check() just returns NULL silently for slab pages).
>
> Yeah LGTM.
I agree that snapshot_page() is an overkill here and reusing the
memcg_data snapshot looks good to me.
--
Best Regards,
Yan, Zi
next prev parent reply other threads:[~2026-07-13 19:27 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-01 6:10 [PATCH v5 0/9] mm/page_owner: misc cleanups Ye Liu
2026-07-01 6:10 ` [PATCH v5 1/9] mm/page_owner: extract skip_buddy_pages() helper to unify buddy page skipping Ye Liu
2026-07-01 6:10 ` [PATCH v5 2/9] mm/page_owner: add MR_NEVER to enum migrate_reason and use it for last_migrate_reason Ye Liu
2026-07-01 6:10 ` [PATCH v5 3/9] mm: use enum migrate_reason instead of int for migration reason parameters Ye Liu
2026-07-01 10:23 ` Lorenzo Stoakes
2026-07-06 18:34 ` David Hildenbrand (Arm)
2026-07-01 6:10 ` [PATCH v5 4/9] mm/page_owner: hoist CONFIG_MEMCG to function level for print_page_owner_memcg() Ye Liu
2026-07-01 6:10 ` [PATCH v5 5/9] mm/page_owner: add missing newline to count_threshold format string Ye Liu
2026-07-01 6:10 ` [PATCH v5 6/9] mm/page_owner: move free_ts_nsec output to free section in __dump_page_owner() Ye Liu
2026-07-01 6:10 ` [PATCH v5 7/9] mm/page_owner: drop redundant page_owner prefix from static symbols Ye Liu
2026-07-01 6:10 ` [PATCH v5 8/9] mm/page_owner: clamp skip_buddy_pages() PFN advance at MAX_ORDER_NR_PAGES boundary Ye Liu
2026-07-01 6:34 ` Vlastimil Babka (SUSE)
2026-07-02 2:44 ` Zi Yan
2026-07-01 6:10 ` [PATCH v5 9/9] mm/page_owner: use memcg_data snapshot instead of PageMemcgKmem() to avoid TOCTOU VM_BUG_ON Ye Liu
2026-07-01 6:49 ` Vlastimil Babka (SUSE)
2026-07-02 2:02 ` Zi Yan
2026-07-10 6:51 ` Ye Liu
2026-07-10 15:56 ` Zi Yan
2026-07-13 2:40 ` Ye Liu
2026-07-13 17:34 ` Vlastimil Babka (SUSE)
2026-07-13 19:27 ` Zi Yan [this message]
2026-07-02 0:11 ` [PATCH v5 0/9] mm/page_owner: misc cleanups Andrew Morton
2026-07-10 7:05 ` Ye Liu
2026-07-10 21:27 ` Andrew Morton
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=DJXOW0P35L9B.395DKD4LXEA3R@nvidia.com \
--to=ziy@nvidia.com \
--cc=akpm@linux-foundation.org \
--cc=hannes@cmpxchg.org \
--cc=jackmanb@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mhocko@suse.com \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=ye.liu@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.