All of lore.kernel.org
 help / color / mirror / Atom feed
From: "David Hildenbrand (Arm)" <david@kernel.org>
To: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>, linux-mm@kvack.org
Cc: akpm@linux-foundation.org, vbabka@suse.cz, surenb@google.com,
	mhocko@suse.com, jackmanb@google.com, hannes@cmpxchg.org,
	ziy@nvidia.com, npiggin@gmail.com, linux-kernel@vger.kernel.org,
	kasong@tencent.com, hughd@google.com, chrisl@kernel.org,
	ryncsn@gmail.com, stable@vger.kernel.org, willy@infradead.org
Subject: Re: [PATCH v3] mm/page_alloc: clear page->private in free_pages_prepare()
Date: Sat, 7 Feb 2026 23:02:27 +0100	[thread overview]
Message-ID: <cbc3b5b3-09b5-4e3c-99f0-a1f67582afff@kernel.org> (raw)
In-Reply-To: <20260207173615.146159-1-mikhail.v.gavrilov@gmail.com>

On 2/7/26 18:36, Mikhail Gavrilov wrote:

Thanks!

> Several subsystems (slub, shmem, ttm, etc.) use page->private but don't
> clear it before freeing pages. When these pages are later allocated as
> high-order pages and split via split_page(), tail pages retain stale
> page->private values.
> 
> This causes a use-after-free in the swap subsystem. The swap code uses
> page->private to track swap count continuations, assuming freshly
> allocated pages have page->private == 0. When stale values are present,
> swap_count_continued() incorrectly assumes the continuation list is valid
> and iterates over uninitialized page->lru containing LIST_POISON values,
> causing a crash:
> 
>    KASAN: maybe wild-memory-access in range [0xdead000000000100-0xdead000000000107]
>    RIP: 0010:__do_sys_swapoff+0x1151/0x1860
> 
> Fix this by clearing page->private in free_pages_prepare(), ensuring all
> freed pages have clean state regardless of previous use.

I could have sworn we discussed something like that already in the past.

I recall that freeing pages with page->private set was allowed. Although
I once wondered whether we should actually change that.

> 
> Fixes: 3b8000ae185c ("mm/vmalloc: huge vmalloc backing pages should be split rather than compound")
> Cc: stable@vger.kernel.org
> Suggested-by: Zi Yan <ziy@nvidia.com>
> Acked-by: Zi Yan <ziy@nvidia.com>
> Signed-off-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
> ---

Next time, please don't send patches as reply to another thread; that
way it can easily get lost in a bigger thread.

You want to get peoples attention :)

>   mm/page_alloc.c | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index cbf758e27aa2..24ac34199f95 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -1430,6 +1430,7 @@ __always_inline bool free_pages_prepare(struct page *page,
>   
>   	page_cpupid_reset_last(page);
>   	page->flags.f &= ~PAGE_FLAGS_CHECK_AT_PREP;
> +	page->private = 0;

Should we be using set_page_private()? It's a bit inconsistent :)

I wonder, if it's really just the split_page() problem, why not
handle it there, where we already iterate over all ("tail") pages?

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index cbf758e27aa2..cbbcfdf3ed26 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3122,8 +3122,10 @@ void split_page(struct page *page, unsigned int order)
         VM_BUG_ON_PAGE(PageCompound(page), page);
         VM_BUG_ON_PAGE(!page_count(page), page);
  
-       for (i = 1; i < (1 << order); i++)
+       for (i = 1; i < (1 << order); i++) {
                 set_page_refcounted(page + i);
+               set_page_private(page, 0);
+       }
         split_page_owner(page, order, 0);
         pgalloc_tag_split(page_folio(page), order, 0);
         split_page_memcg(page, order);


But then I thought about "what does actually happen during an folio split".

We had a check in __split_folio_to_order() that got removed in 4265d67e405a, for some
undocumented reason (and the patch got merged with 0 tags :( ). I assume because with zone-device
there was a way to now got ->private properly set. But we removed the safety check for
all other folios.

-               /*
-                * page->private should not be set in tail pages. Fix up and warn once
-                * if private is unexpectedly set.
-                */
-               if (unlikely(new_folio->private)) {
-                       VM_WARN_ON_ONCE_PAGE(true, new_head);
-                       new_folio->private = NULL;
-               }


I would have thought that we could have triggered that check easily before. Why didn't we?

Who would have cleared the private field of tail pages?

@Zi Yan, any idea why the folio splitting code wouldn't have revealed a similar problem?

-- 
Cheers,

David


  reply	other threads:[~2026-02-07 22:02 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CABXGCs03XcXt5GDae7d74ynC6P6G2gLw3ZrwAYvSQ3PwP0mGXA@mail.gmail.com>
2026-02-06 17:40 ` [PATCH] mm/page_alloc: clear page->private in split_page() for tail pages Mikhail Gavrilov
2026-02-06 18:08   ` Zi Yan
2026-02-06 18:21     ` Mikhail Gavrilov
2026-02-06 18:29       ` Zi Yan
2026-02-06 18:33         ` Zi Yan
2026-02-06 19:58           ` Zi Yan
2026-02-06 20:49             ` Zi Yan
2026-02-06 22:16               ` Mikhail Gavrilov
2026-02-06 22:37                 ` Mikhail Gavrilov
2026-02-06 23:06                   ` Zi Yan
2026-02-07  3:28                     ` Zi Yan
2026-02-07 14:25                       ` Mikhail Gavrilov
2026-02-07 14:32                         ` Zi Yan
2026-02-07 15:03                           ` Mikhail Gavrilov
2026-02-07 15:06                             ` Zi Yan
2026-02-07 15:37                               ` [PATCH v2] mm/page_alloc: clear page->private in free_pages_prepare() Mikhail Gavrilov
2026-02-07 16:12                                 ` Zi Yan
2026-02-07 17:36                                   ` [PATCH v3] " Mikhail Gavrilov
2026-02-07 22:02                                     ` David Hildenbrand (Arm) [this message]
2026-02-07 22:08                                       ` David Hildenbrand (Arm)
2026-02-09 11:17                                         ` Vlastimil Babka
2026-02-09 15:46                                           ` David Hildenbrand (Arm)
2026-02-09 16:00                                             ` Zi Yan
2026-02-09 16:03                                               ` David Hildenbrand (Arm)
2026-02-09 16:05                                                 ` Zi Yan
2026-02-09 16:06                                                   ` David Hildenbrand (Arm)
2026-02-09 16:08                                                     ` Zi Yan
2026-02-07 23:00                                       ` Zi Yan
2026-02-09 16:16                                         ` David Hildenbrand (Arm)
2026-02-09 16:20                                           ` David Hildenbrand (Arm)
2026-02-09 16:33                                             ` Zi Yan
2026-02-09 17:36                                               ` David Hildenbrand (Arm)
2026-02-09 17:44                                                 ` Zi Yan
2026-02-09 19:39                                                   ` David Hildenbrand (Arm)
2026-02-09 19:42                                                     ` Zi Yan
2026-02-10  1:20                                                       ` Baolin Wang
2026-02-10  2:12                                                         ` Zi Yan
2026-02-10  2:25                                                           ` Baolin Wang
2026-02-10  2:32                                                             ` Zi Yan
2026-02-09 19:46                                     ` David Hildenbrand (Arm)
2026-02-09 11:11                                 ` [PATCH v2] " Vlastimil Babka
2026-02-06 18:24     ` [PATCH] mm/page_alloc: clear page->private in split_page() for tail pages Kairui Song

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=cbc3b5b3-09b5-4e3c-99f0-a1f67582afff@kernel.org \
    --to=david@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=chrisl@kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=hughd@google.com \
    --cc=jackmanb@google.com \
    --cc=kasong@tencent.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mhocko@suse.com \
    --cc=mikhail.v.gavrilov@gmail.com \
    --cc=npiggin@gmail.com \
    --cc=ryncsn@gmail.com \
    --cc=stable@vger.kernel.org \
    --cc=surenb@google.com \
    --cc=vbabka@suse.cz \
    --cc=willy@infradead.org \
    --cc=ziy@nvidia.com \
    /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.