From: "David Hildenbrand (Arm)" <david@kernel.org>
To: Kiryl Shutsemau <kirill@shutemov.name>,
Andrew Morton <akpm@linux-foundation.org>,
Lorenzo Stoakes <ljs@kernel.org>,
Miaohe Lin <linmiaohe@huawei.com>,
Naoya Horiguchi <nao.horiguchi@gmail.com>
Cc: Zi Yan <ziy@nvidia.com>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
"Liam R . Howlett" <liam@infradead.org>,
Nico Pache <npache@redhat.com>,
Ryan Roberts <ryan.roberts@arm.com>, Dev Jain <dev.jain@arm.com>,
Barry Song <baohua@kernel.org>, Lance Yang <lance.yang@linux.dev>,
Usama Arif <usama.arif@linux.dev>,
Hao Zhang <zhanghao1@kylinos.cn>,
Hao Zhang <hao_zhang_kdev@163.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
"Kiryl Shutsemau (Meta)" <kas@kernel.org>,
stable@vger.kernel.org
Subject: Re: [PATCH v2 1/5] mm/memory-failure: keep the folio, not the poisoned subpage, locked across split
Date: Tue, 14 Jul 2026 15:01:46 +0200 [thread overview]
Message-ID: <c4aa63df-30ab-464d-bd0b-48dc37c8e6ba@kernel.org> (raw)
In-Reply-To: <20260714122344.351895-2-kirill@shutemov.name>
On 7/14/26 14:23, Kiryl Shutsemau wrote:
> From: "Kiryl Shutsemau (Meta)" <kas@kernel.org>
>
> try_to_split_thp_page() locked the poisoned page and passed it to
> split_huge_page_to_order(), which returns that very page locked to the
> caller. For a tail page that means __folio_split() runs with @lock_at
> pointing into the middle of the folio.
>
> __folio_split() dereferences the mapping after the split completes
> (shmem_uncharge(), i_mmap_unlock_read()). The only thing keeping the
> inode alive across that is the locked @lock_at folio: while it stays in
> the page cache, eviction cannot complete.
>
> But a tail @lock_at can lie beyond EOF -- e.g. part of a shmem THP that
> reaches past i_size while the file is being truncated. The split then
> drops it from the page cache yet still returns it locked, so the pin is
> gone and a racing final iput() can evict and RCU-free the inode while
> __folio_split() is still running:
>
> BUG: KASAN: slab-use-after-free in __up_read+0x634/0x790
> i_mmap_unlock_read include/linux/fs.h:537 [inline]
> __folio_split+0x732/0x1640 mm/huge_memory.c:4100
> try_to_split_thp_page+0xab/0x390 mm/memory-failure.c:1675
> memory_failure+0x1394/0x26e0 mm/memory-failure.c:2470
>
> Freed by task 4601:
> shmem_free_in_core_inode+0x54/0xb0 mm/shmem.c:5177
> evict+0x57f/0xac0 fs/inode.c:870
>
> Split the folio as a folio, via split_folio_to_order(), so the head is
> the anchor left locked. The head is piece 0, which the beyond-EOF drop
> loop never removes (it starts at folio_next(folio)), so the split always
> leaves it in the page cache and the inode stays pinned for the whole of
> __folio_split(). memory_failure() and soft offline re-lock the poisoned
> subpage's folio themselves after the split, so they do not depend on it
> being returned locked.
>
> Reported-by: Hao Zhang <zhanghao1@kylinos.cn>
> Closes: https://lore.kernel.org/linux-mm/20260710071344.GA106129@zh-pc
> Fixes: baa355fd3314 ("thp: file pages support for split_huge_page()")
> Cc: <stable@vger.kernel.org>
> Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
> ---
> mm/memory-failure.c | 13 ++++++++++---
> 1 file changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/mm/memory-failure.c b/mm/memory-failure.c
> index 51508a55c405..68d42cbed458 100644
> --- a/mm/memory-failure.c
> +++ b/mm/memory-failure.c
> @@ -1657,11 +1657,18 @@ static int identify_page_state(unsigned long pfn, struct page *p,
> static int try_to_split_thp_page(struct page *page, unsigned int new_order,
> bool release)
> {
> + struct folio *folio = page_folio(page);
> int ret;
>
> - lock_page(page);
> - ret = split_huge_page_to_order(page, new_order);
> - unlock_page(page);
> + /*
> + * Lock and split at the head, not the poisoned subpage: __folio_split()
> + * keeps the anchor folio locked and needs it to stay in the page cache
> + * to pin the inode. A tail beyond EOF would be dropped yet returned
> + * locked, losing that pin. The caller re-locks @page afterwards.
> + */
> + folio_lock(folio);
> + ret = split_folio_to_order(folio, new_order);
> + folio_unlock(folio);
With a non-uniform split it would actually make a difference: we'd want to split
such that we the other folio pages minimal.
split_folio_to_order() always seems to end up in
__split_huge_page_to_list_to_order() where we do a SPLIT_TYPE_UNIFORM.
I recall discussing with Zi and Willy that in the future we'd want to convert
more places to do a non-uniform split.
So I'm afraid that would just re-introduce the problem then.
--
Cheers,
David
next prev parent reply other threads:[~2026-07-14 13:01 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-14 12:23 [PATCH v2 0/5] mm: fix inode UAF when splitting a file folio past EOF Kiryl Shutsemau
2026-07-14 12:23 ` [PATCH v2 1/5] mm/memory-failure: keep the folio, not the poisoned subpage, locked across split Kiryl Shutsemau
2026-07-14 13:01 ` David Hildenbrand (Arm) [this message]
2026-07-14 14:53 ` Kiryl Shutsemau
2026-07-14 14:58 ` David Hildenbrand (Arm)
2026-07-14 15:44 ` Zi Yan
2026-07-14 16:40 ` Kiryl Shutsemau
2026-07-14 17:31 ` Zi Yan
2026-07-14 13:05 ` Kiryl Shutsemau
2026-07-14 12:23 ` [PATCH v2 2/5] mm/huge_memory: refuse to split a file folio when the anchor is beyond EOF Kiryl Shutsemau
2026-07-14 12:23 ` [PATCH v2 3/5] mm/huge_memory: remove unused split_huge_page_to_order() Kiryl Shutsemau
2026-07-14 12:23 ` [PATCH v2 4/5] mm/huge_memory: remove unused can_split_folio() Kiryl Shutsemau
2026-07-14 12:23 ` [PATCH v2 5/5] mm/huge_memory: fold split_folio_to_list_to_order() into split_folio_to_order() Kiryl Shutsemau
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=c4aa63df-30ab-464d-bd0b-48dc37c8e6ba@kernel.org \
--to=david@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=dev.jain@arm.com \
--cc=hao_zhang_kdev@163.com \
--cc=kas@kernel.org \
--cc=kirill@shutemov.name \
--cc=lance.yang@linux.dev \
--cc=liam@infradead.org \
--cc=linmiaohe@huawei.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=nao.horiguchi@gmail.com \
--cc=npache@redhat.com \
--cc=ryan.roberts@arm.com \
--cc=stable@vger.kernel.org \
--cc=usama.arif@linux.dev \
--cc=zhanghao1@kylinos.cn \
--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.