From: Daejun Park print_page_owner_memcg() loads memcg_data before it tests PageTail(). In the first tail page, memcg_data holds the folio's _nr_pages. A split can make the page a folio between the two loads. The stale _nr_pages then passes the PageTail() test and is used as an objcg pointer. __split_folio_to_order() stores memcg_data before the smp_wmb() that precedes clear_compound_head(). Also test PageTail() before the load, with a paired smp_rmb(). Keep the test after the load for a page that becomes a tail in between. Fixes: 4996fc547f5b ("mm: let _folio_nr_pages overlay memcg_data in first tail page") Signed-off-by: Daejun Park --- Needs patch 1 for the store order. Found by reading the code, not reproduced. The page_owner oops seen with a delay after clear_compound_head() is the window patch 1 closes. --- mm/page_owner.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mm/page_owner.c b/mm/page_owner.c index cfc31c92d7..058d4dec84 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c @@ -564,6 +564,13 @@ static inline int print_page_owner_memcg(char *kbuf, size_t count, int ret, char name[80]; rcu_read_lock(); + if (PageTail(page)) + goto out_unlock; + /* + * Order the memcg_data load after the PageTail() load. Pairs with + * smp_wmb() in __split_folio_to_order(). + */ + smp_rmb(); memcg_data = READ_ONCE(page->memcg_data); if (!memcg_data || PageTail(page)) goto out_unlock; -- 2.43.0