* [PATCH] mm/migrate: snapshot the source nid before the misplaced migration
@ 2026-10-23 2:32 Yafang Shao
2026-10-23 3:28 ` Matthew Wilcox
0 siblings, 1 reply; 6+ messages in thread
From: Yafang Shao @ 2026-10-23 2:32 UTC (permalink / raw)
To: akpm, david, ziy, matthew.brost, joshua.hahnjy, byungchul, gourry,
ying.huang, apopple
Cc: linux-mm, Yafang Shao, Huang, Ying
A successful migration frees the source folio, so the folio_nid() read
in the promotion counter update can pick up a reallocated page's nid.
Snapshot the nid before the migration, next to the memcg snapshot the
function already takes.
Fixes: e39bb6be9f2b ("NUMA Balancing: add page promotion counter")
Signed-off-by: Yafang Shao <laoar.shao@gmail.com>
Cc: "Huang, Ying" <ying.huang@intel.com>
---
mm/migrate.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
---
This was found while implementing the BPF-NUMAB series. No real issues occurred.
diff --git a/mm/migrate.c b/mm/migrate.c
index 15b45832bcfa..91ba064e1bf4 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -2757,6 +2757,7 @@ int migrate_misplaced_folio(struct folio *folio, int node)
pg_data_t *pgdat = NODE_DATA(node);
int nr_remaining;
unsigned int nr_succeeded;
+ int src_node = folio_nid(folio);
LIST_HEAD(migratepages);
struct mem_cgroup *memcg = get_mem_cgroup_from_folio(folio);
struct lruvec *lruvec = mem_cgroup_lruvec(memcg, pgdat);
@@ -2771,7 +2772,7 @@ int migrate_misplaced_folio(struct folio *folio, int node)
count_vm_numa_events(NUMA_PAGE_MIGRATE, nr_succeeded);
count_memcg_events(memcg, NUMA_PAGE_MIGRATE, nr_succeeded);
if ((sysctl_numa_balancing_mode & NUMA_BALANCING_MEMORY_TIERING)
- && !node_is_toptier(folio_nid(folio))
+ && !node_is_toptier(src_node)
&& node_is_toptier(node))
mod_lruvec_state(lruvec, PGPROMOTE_SUCCESS, nr_succeeded);
}
--
2.52.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] mm/migrate: snapshot the source nid before the misplaced migration
2026-10-23 2:32 [PATCH] mm/migrate: snapshot the source nid before the misplaced migration Yafang Shao
@ 2026-10-23 3:28 ` Matthew Wilcox
2026-10-23 3:48 ` Yafang Shao
2026-10-23 14:11 ` Zi Yan
0 siblings, 2 replies; 6+ messages in thread
From: Matthew Wilcox @ 2026-10-23 3:28 UTC (permalink / raw)
To: Yafang Shao
Cc: akpm, david, ziy, matthew.brost, joshua.hahnjy, byungchul, gourry,
ying.huang, apopple, linux-mm, Huang, Ying
On Fri, Oct 23, 2026 at 10:32:26AM +0800, Yafang Shao wrote:
> A successful migration frees the source folio, so the folio_nid() read
> in the promotion counter update can pick up a reallocated page's nid.
> Snapshot the nid before the migration, next to the memcg snapshot the
> function already takes.
I don't understand how a node ID can change even after the folio has
been freed. I don't think this patch is wrong, but I don't think
there's actually a bug here that's being fixed.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] mm/migrate: snapshot the source nid before the misplaced migration
2026-10-23 3:28 ` Matthew Wilcox
@ 2026-10-23 3:48 ` Yafang Shao
2026-10-23 14:11 ` Zi Yan
1 sibling, 0 replies; 6+ messages in thread
From: Yafang Shao @ 2026-10-23 3:48 UTC (permalink / raw)
To: Matthew Wilcox
Cc: akpm, david, ziy, matthew.brost, joshua.hahnjy, byungchul, gourry,
ying.huang, apopple, linux-mm, Huang, Ying
On Fri, Oct 23, 2026 at 11:29 AM Matthew Wilcox <willy@infradead.org> wrote:
>
> On Fri, Oct 23, 2026 at 10:32:26AM +0800, Yafang Shao wrote:
> > A successful migration frees the source folio, so the folio_nid() read
> > in the promotion counter update can pick up a reallocated page's nid.
> > Snapshot the nid before the migration, next to the memcg snapshot the
> > function already takes.
>
> I don't understand how a node ID can change even after the folio has
> been freed. I don't think this patch is wrong, but I don't think
> there's actually a bug here that's being fixed.
You are right.
The node bits in page->flags encode the physical node and the
allocator does not touch them. There is no observable bug here.
--
Regards
Yafang
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] mm/migrate: snapshot the source nid before the misplaced migration
2026-10-23 3:28 ` Matthew Wilcox
2026-10-23 3:48 ` Yafang Shao
@ 2026-10-23 14:11 ` Zi Yan
2026-10-25 3:51 ` Yafang Shao
2026-10-25 11:19 ` Matthew Wilcox
1 sibling, 2 replies; 6+ messages in thread
From: Zi Yan @ 2026-10-23 14:11 UTC (permalink / raw)
To: Matthew Wilcox, Yafang Shao
Cc: akpm, david, matthew.brost, joshua.hahnjy, byungchul, gourry,
ying.huang, apopple, linux-mm, Huang, Ying
On Thu Oct 22, 2026 at 11:28 PM EDT, Matthew Wilcox wrote:
> On Fri, Oct 23, 2026 at 10:32:26AM +0800, Yafang Shao wrote:
>> A successful migration frees the source folio, so the folio_nid() read
>> in the promotion counter update can pick up a reallocated page's nid.
>> Snapshot the nid before the migration, next to the memcg snapshot the
>> function already takes.
>
> I don't understand how a node ID can change even after the folio has
> been freed. I don't think this patch is wrong, but I don't think
I agree with you in the current code base.
> there's actually a bug here that's being fixed.
Strictly speaking, it can be seen as a benign UAF. It works, because
1. folio->flags happens to be the same as page->flags,
2. folio/page nid is stored in the ->flags and never changed.
In memdesc world, after a folio is freed, I assume folio->flags would be
zeroed since struct folio is freed and calling folio_nid() on a freed
folio would give a bogus result (yeah, it can be mitigated by not
zeroing node field and each node has its own struct folio pool, but that
makes folio_nid() implementation dependent).
IMHO, this patch is still worth getting in.
--
Best Regards,
Yan, Zi
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] mm/migrate: snapshot the source nid before the misplaced migration
2026-10-23 14:11 ` Zi Yan
@ 2026-10-25 3:51 ` Yafang Shao
2026-10-25 11:19 ` Matthew Wilcox
1 sibling, 0 replies; 6+ messages in thread
From: Yafang Shao @ 2026-10-25 3:51 UTC (permalink / raw)
To: Zi Yan
Cc: Matthew Wilcox, akpm, david, matthew.brost, joshua.hahnjy,
byungchul, gourry, ying.huang, apopple, linux-mm, Huang, Ying
On Fri, Oct 23, 2026 at 10:11 PM Zi Yan <ziy@nvidia.com> wrote:
>
> On Thu Oct 22, 2026 at 11:28 PM EDT, Matthew Wilcox wrote:
> > On Fri, Oct 23, 2026 at 10:32:26AM +0800, Yafang Shao wrote:
> >> A successful migration frees the source folio, so the folio_nid() read
> >> in the promotion counter update can pick up a reallocated page's nid.
> >> Snapshot the nid before the migration, next to the memcg snapshot the
> >> function already takes.
> >
> > I don't understand how a node ID can change even after the folio has
> > been freed. I don't think this patch is wrong, but I don't think
>
> I agree with you in the current code base.
>
> > there's actually a bug here that's being fixed.
>
> Strictly speaking, it can be seen as a benign UAF. It works, because
>
> 1. folio->flags happens to be the same as page->flags,
> 2. folio/page nid is stored in the ->flags and never changed.
>
> In memdesc world, after a folio is freed, I assume folio->flags would be
> zeroed since struct folio is freed and calling folio_nid() on a freed
> folio would give a bogus result (yeah, it can be mitigated by not
> zeroing node field and each node has its own struct folio pool, but that
> makes folio_nid() implementation dependent).
>
> IMHO, this patch is still worth getting in.
Thanks for the careful review. I will refine the commit message
and send a new version.
--
Regards
Yafang
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] mm/migrate: snapshot the source nid before the misplaced migration
2026-10-23 14:11 ` Zi Yan
2026-10-25 3:51 ` Yafang Shao
@ 2026-10-25 11:19 ` Matthew Wilcox
1 sibling, 0 replies; 6+ messages in thread
From: Matthew Wilcox @ 2026-10-25 11:19 UTC (permalink / raw)
To: Zi Yan
Cc: Yafang Shao, akpm, david, matthew.brost, joshua.hahnjy, byungchul,
gourry, ying.huang, apopple, linux-mm, Huang, Ying
On Fri, Oct 23, 2026 at 10:11:34AM -0400, Zi Yan wrote:
> On Thu Oct 22, 2026 at 11:28 PM EDT, Matthew Wilcox wrote:
> > On Fri, Oct 23, 2026 at 10:32:26AM +0800, Yafang Shao wrote:
> >> A successful migration frees the source folio, so the folio_nid() read
> >> in the promotion counter update can pick up a reallocated page's nid.
> >> Snapshot the nid before the migration, next to the memcg snapshot the
> >> function already takes.
> >
> > I don't understand how a node ID can change even after the folio has
> > been freed. I don't think this patch is wrong, but I don't think
>
> I agree with you in the current code base.
>
> > there's actually a bug here that's being fixed.
>
> Strictly speaking, it can be seen as a benign UAF. It works, because
>
> 1. folio->flags happens to be the same as page->flags,
> 2. folio/page nid is stored in the ->flags and never changed.
>
> In memdesc world, after a folio is freed, I assume folio->flags would be
> zeroed since struct folio is freed and calling folio_nid() on a freed
> folio would give a bogus result (yeah, it can be mitigated by not
> zeroing node field and each node has its own struct folio pool, but that
> makes folio_nid() implementation dependent).
Oh, once struct folio is separately allocated, it's a UAF. It could be
recycled to a different NID or maybe the slab containing the folio could
be freed (assuming we're not holding the RCU read lock at this point in
migration, and I don't see why we would be).
With a better commit message, I have no objection to this patch.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-25 11:19 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-23 2:32 [PATCH] mm/migrate: snapshot the source nid before the misplaced migration Yafang Shao
2026-10-23 3:28 ` Matthew Wilcox
2026-10-23 3:48 ` Yafang Shao
2026-10-23 14:11 ` Zi Yan
2026-10-25 3:51 ` Yafang Shao
2026-10-25 11:19 ` Matthew Wilcox
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.