* [PATCH] mm/util: fix off-by-one when checking folio index in snapshot_page()
@ 2026-11-14 16:46 shao.mingyin
2026-11-14 17:33 ` Lorenzo Stoakes (ARM)
2026-11-15 16:47 ` sashiko-bot
0 siblings, 2 replies; 4+ messages in thread
From: shao.mingyin @ 2026-11-14 16:46 UTC (permalink / raw)
To: akpm, david; +Cc: linux-mm, liam, vbabka, rppt, surenb, mhocko, linux-kernel
From: Shao Mingyin <shao.mingyin@zte.com.cn>
mm/util: fix off-by-one when checking folio index in snapshot_page()
snapshot_page() computes the page index before copying the folio state.
If the folio changes between those reads, the index can equal the copied
folio's page count. Valid indices are strictly less than that count,
but the current check accepts equality and marks the snapshot faithful.
Use >= so that this inconsistent snapshot is retried, or falls back to
the unfaithful single-page representation. This also avoids reporting an
out-of-range folio index without the corresponding dump_page() warning.
Fixes: d863a12108f2 ("mm/util: introduce snapshot_page()")
Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
---
Build-tested mm/util.o with W=1 on x86_64. The boundary check was
reviewed statically; the folio-split race has not been reproduced.
mm/util.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/util.c b/mm/util.c
index a5140b3b70f3305cd78144a54d3b15a794da9609..6e6a8f8640a75ebb0f81f54c9a5085f698320714 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -1462,7 +1462,7 @@ void snapshot_page(struct page_snapshot *ps, const struct page *page)
set_ps_flags(ps, foliop, page);
}
- if (ps->idx > nr_pages) {
+ if (ps->idx >= nr_pages) {
if (loops-- > 0)
goto again;
clear_compound_head(&ps->page_snapshot);
base-commit: 84abb955b1015477aa11a96e2f3ac1b938b77f48
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] mm/util: fix off-by-one when checking folio index in snapshot_page()
2026-11-14 16:46 [PATCH] mm/util: fix off-by-one when checking folio index in snapshot_page() shao.mingyin
@ 2026-11-14 17:33 ` Lorenzo Stoakes (ARM)
2026-11-15 17:32 ` David Hildenbrand (Arm)
2026-11-15 16:47 ` sashiko-bot
1 sibling, 1 reply; 4+ messages in thread
From: Lorenzo Stoakes (ARM) @ 2026-11-14 17:33 UTC (permalink / raw)
To: shao.mingyin
Cc: akpm, david, linux-mm, liam, vbabka, rppt, surenb, mhocko,
linux-kernel
On Sun, Nov 15, 2026 at 12:46:57AM +0800, shao.mingyin@zte.com.cn wrote:
> From: Shao Mingyin <shao.mingyin@zte.com.cn>
>
> mm/util: fix off-by-one when checking folio index in snapshot_page()
>
> snapshot_page() computes the page index before copying the folio state.
> If the folio changes between those reads, the index can equal the copied
> folio's page count. Valid indices are strictly less than that count,
> but the current check accepts equality and marks the snapshot faithful.
>
> Use >= so that this inconsistent snapshot is retried, or falls back to
> the unfaithful single-page representation. This also avoids reporting an
> out-of-range folio index without the corresponding dump_page() warning.
>
> Fixes: d863a12108f2 ("mm/util: introduce snapshot_page()")
> Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
NAK.
this is generated by some AI slopper's script, spamming the kernel. The
patches I looked at were wrong/broken, so no to anything from this person.
They've sent 300 mails in under four weeks spanniing: ata, scsi, target,
ufs, nvme/nvmet, ubifs, ublk, zloop, dm, md, mmc, virtio-blk, mfd, gpio,
pwm, spi, PCI, ASoC, ACPI, net, vfs mount, block partitions, and now mm.
and 17 series across 7 subsystems over the past 23 hours.
We need a way to ban emails from people like this...
--
Cheers, Lorenzo
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] mm/util: fix off-by-one when checking folio index in snapshot_page()
2026-11-14 16:46 [PATCH] mm/util: fix off-by-one when checking folio index in snapshot_page() shao.mingyin
2026-11-14 17:33 ` Lorenzo Stoakes (ARM)
@ 2026-11-15 16:47 ` sashiko-bot
1 sibling, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-11-15 16:47 UTC (permalink / raw)
To: shao.mingyin, akpm, david; +Cc: linux-mm, liam, vbabka, rppt, surenb, mhocko
Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] mm/util: head page with zero _nr_pages hits tail fallback in
snapshot_page()
--
commit c1bbaeb218bb3e6717e9e858cb2ae698eb9ee371
Author: Shao Mingyin <shao.mingyin@zte.com.cn>
mm/util: fix off-by-one when checking folio index in snapshot_page()
This commit changes the folio index bounds check in snapshot_page() from
> to >= so that snapshots whose page index equals the copied folio's
page count are retried or treated as unfaithful.
> diff --git a/mm/util.c b/mm/util.c
> index a5140b3b70f33..6e6a8f8640a75 100644
> --- a/mm/util.c
> +++ b/mm/util.c
> @@ -1462,7 +1462,7 @@ void snapshot_page(struct page_snapshot *ps, const struct page *page)
> set_ps_flags(ps, foliop, page);
> }
>
> - if (ps->idx > nr_pages) {
> + if (ps->idx >= nr_pages) {
> if (loops-- > 0)
> goto again;
> clear_compound_head(&ps->page_snapshot);
[Severity: Medium]
Can this cause a compound head page with folio->_nr_pages == 0 to enter
the tail-page fallback block?
When snapshot_page() inspects a compound head page (ps->idx == 0) while
folio->_nr_pages is 0 under NR_PAGES_IN_LARGE_FOLIO, nr_pages is 0 and
ps->idx >= nr_pages now evaluates to true. This happens deterministically
when __free_pages_prepare() reports a bad compound page, because it zeroes
folio->_nr_pages before calling free_page_is_bad() -> bad_page() ->
dump_page() and before clearing PG_head:
mm/page_alloc.c:__free_pages_prepare() {
...
if (compound) {
page[1].flags.f &= ~PAGE_FLAGS_SECOND;
#ifdef NR_PAGES_IN_LARGE_FOLIO
folio->_nr_pages = 0;
#endif
}
...
if (is_check_pages_enabled()) {
if (free_page_is_bad(page))
bad++;
...
}
After the retries expire, the fallback calls
clear_compound_head(&ps->page_snapshot), which overwrites the compound_info
union word (lru.next or pp_magic on a head page) with 0, copies only
sizeof(struct page) into ps->folio_snapshot while leaving PG_head set, and
clears ps->flags. In __dump_page(), this triggers a bogus "page does not
match folio" warning on a head page and zeroes the lru.next word in the hex
dump.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261115004657890Pz8ERDf5nCtE-B6M7KFzu@zte.com.cn?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] mm/util: fix off-by-one when checking folio index in snapshot_page()
2026-11-14 17:33 ` Lorenzo Stoakes (ARM)
@ 2026-11-15 17:32 ` David Hildenbrand (Arm)
0 siblings, 0 replies; 4+ messages in thread
From: David Hildenbrand (Arm) @ 2026-11-15 17:32 UTC (permalink / raw)
To: Lorenzo Stoakes (ARM), shao.mingyin
Cc: akpm, linux-mm, liam, vbabka, rppt, surenb, mhocko, linux-kernel
On 11/14/26 18:33, Lorenzo Stoakes (ARM) wrote:
> On Sun, Nov 15, 2026 at 12:46:57AM +0800, shao.mingyin@zte.com.cn wrote:
>> From: Shao Mingyin <shao.mingyin@zte.com.cn>
>>
>> mm/util: fix off-by-one when checking folio index in snapshot_page()
>>
>> snapshot_page() computes the page index before copying the folio state.
>> If the folio changes between those reads, the index can equal the copied
>> folio's page count. Valid indices are strictly less than that count,
>> but the current check accepts equality and marks the snapshot faithful.
>>
>> Use >= so that this inconsistent snapshot is retried, or falls back to
>> the unfaithful single-page representation. This also avoids reporting an
>> out-of-range folio index without the corresponding dump_page() warning.
>>
>> Fixes: d863a12108f2 ("mm/util: introduce snapshot_page()")
>> Signed-off-by: Shao Mingyin <shao.mingyin@zte.com.cn>
>
> NAK.
Let's do the following:. Thoughts?
From c7d1a79926e3b3448bb5e84f901c185234f43b52 Mon Sep 17 00:00:00 2001
From: "David Hildenbrand (Arm)" <david@kernel.org>
Date: Sun, 15 Nov 2026 18:11:08 +0100
Subject: [PATCH] mm/util: fix retry detection and handling in snapshot_page()
snapshot_page() detects races with concurrent folio split+construction by
checking whether the given page still falls into the folio. Unfortunately,
we have an off-by-one error in there, and we should be checking for
"ps->idx >= nr_pages", because idx 0 is valid.
For example, we might currently report a tail page at idx 1 as faithful,
although the snapshotted folio is now a small folio.
However, there is one complication: As we don't hold a folio reference,
folio_nr_pages() can return 0 on races (or when called from page freeing
code). Handle that by just setting it to 1 in that case, so we don't
wrongly report a head page as "page does not match folio".
In addition, we should reset ps->flags when retrying, by just resetting
it to PAGE_SNAPSHOT_FAITHFUL. Otherwise, PAGE_SNAPSHOT_PG_BUDDY and
PAGE_SNAPSHOT_PG_IDLE from a failed attempt could stick around.
These races are fairly rare, so this is not really critical, we simply
report something slightly wrong. No need to CC stable.
Fixes: d863a12108f2 ("mm/util: introduce snapshot_page()")
Reported-by: Shao Mingyin <shao.mingyin@zte.com.cn>
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
mm/util.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/mm/util.c b/mm/util.c
index 80f6c714844f2..3b10d4c2a4fd9 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -1406,9 +1406,9 @@ void snapshot_page(struct page_snapshot *ps, const struct page *page)
int loops = 5;
ps->pfn = page_to_pfn(page);
- ps->flags = PAGE_SNAPSHOT_FAITHFUL;
again:
+ ps->flags = PAGE_SNAPSHOT_FAITHFUL;
memset(&ps->folio_snapshot, 0, sizeof(struct folio));
memcpy(&ps->page_snapshot, page, sizeof(*page));
info = ps->page_snapshot.compound_info;
@@ -1438,13 +1438,16 @@ void snapshot_page(struct page_snapshot *ps, const struct page *page)
if (ps->idx < MAX_FOLIO_NR_PAGES) {
memcpy(&ps->folio_snapshot, foliop, 2 * sizeof(struct page));
nr_pages = folio_nr_pages(&ps->folio_snapshot);
+ /* On races, or when freeing pages, we can read 0. */
+ if (nr_pages == 0)
+ nr_pages = 1;
if (nr_pages > 2)
memcpy(&ps->folio_snapshot.__page_2, &foliop->__page_2,
sizeof(struct page));
set_ps_flags(ps, foliop, page);
}
- if (ps->idx > nr_pages) {
+ if (ps->idx >= nr_pages) {
if (loops-- > 0)
goto again;
clear_compound_head(&ps->page_snapshot);
--
2.56.1
--
Cheers,
David
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-15 17:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-14 16:46 [PATCH] mm/util: fix off-by-one when checking folio index in snapshot_page() shao.mingyin
2026-11-14 17:33 ` Lorenzo Stoakes (ARM)
2026-11-15 17:32 ` David Hildenbrand (Arm)
2026-11-15 16:47 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox