From: "David Hildenbrand (Arm)" <david@kernel.org>
To: Vernon Yang <vernon2gm@gmail.com>,
akpm@linux-foundation.org, ljs@kernel.org
Cc: nico.pache@linux.dev, ryan.roberts@arm.com, dev.jain@arm.com,
baohua@kernel.org, lance.yang@linux.dev, usama.arif@linux.dev,
zokeefe@google.com, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, stable@vger.kernel.org,
Vernon Yang <yanglincheng@kylinos.cn>
Subject: Re: [PATCH v4 2/3] mm: khugepaged: fix folio is used after pte_unmap_unlock()
Date: Mon, 7 Sep 2026 14:26:21 +0200 [thread overview]
Message-ID: <087d76fd-0e1c-485e-bccb-e3ce074439cb@kernel.org> (raw)
In-Reply-To: <20260828055926.346744-3-vernon2gm@gmail.com>
On 8/28/26 07:59, Vernon Yang wrote:
> From: Vernon Yang <yanglincheng@kylinos.cn>
>
> After the page table lock has dropped, the folio can be freed
> concurrently. The trace_mm_khugepaged_scan_pmd() is left with
> a dangling folio pointer.
>
> So using the folio_pfn() before dropping the page table lock, closing
> use-after-free window.
>
> And other pre-existing bug, When the `for (i = 0; i < HPAGE_PMD_NR; i++)`
> iteration to terminate and the folio operation preceding is normal, but
> pfn will be incorrect. so we really only trace the PFN if it really was
> problematic.
>
> About calling the respective trace_xxx() functions separately on success
> and failure, refer to [1].
>
> [1] https://lore.kernel.org/linux-mm/ao6jVbVHLUmuY2UA@gremlin/
>
> Acked-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> Fixes: 7d2eba0557c1 ("mm: add tracepoint for scanning pages")
> Cc: stable@vger.kernel.org
> Signed-off-by: Vernon Yang <yanglincheng@kylinos.cn>
> ---
> include/trace/events/huge_memory.h | 6 +++---
> mm/khugepaged.c | 17 ++++++++++++++---
> 2 files changed, 17 insertions(+), 6 deletions(-)
>
> diff --git a/include/trace/events/huge_memory.h b/include/trace/events/huge_memory.h
> index 7b526528f85b..fa828967e1fb 100644
> --- a/include/trace/events/huge_memory.h
> +++ b/include/trace/events/huge_memory.h
> @@ -55,10 +55,10 @@ SCAN_STATUS
>
> TRACE_EVENT(mm_khugepaged_scan_pmd,
>
> - TP_PROTO(struct mm_struct *mm, struct folio *folio,
> + TP_PROTO(struct mm_struct *mm, unsigned long pfn,
> int referenced, int none_or_zero, int status, int unmapped),
>
> - TP_ARGS(mm, folio, referenced, none_or_zero, status, unmapped),
> + TP_ARGS(mm, pfn, referenced, none_or_zero, status, unmapped),
>
> TP_STRUCT__entry(
> __field(struct mm_struct *, mm)
> @@ -71,7 +71,7 @@ TRACE_EVENT(mm_khugepaged_scan_pmd,
>
> TP_fast_assign(
> __entry->mm = mm;
> - __entry->pfn = folio ? folio_pfn(folio) : -1;
> + __entry->pfn = pfn;
> __entry->referenced = referenced;
> __entry->none_or_zero = none_or_zero;
> __entry->status = status;
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index b597a3e68606..4d360ae87769 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -1612,6 +1612,7 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> enum scan_result result = SCAN_FAIL;
> struct page *page = NULL;
> struct folio *folio = NULL;
> + unsigned long failed_pfn = -1;
> unsigned long addr;
> unsigned long enabled_orders;
> spinlock_t *ptl;
> @@ -1706,11 +1707,13 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> if (cc->is_khugepaged && !(vma->vm_flags & VM_DROPPABLE) &&
> folio_test_lazyfree(folio) && !pte_dirty(pteval)) {
> result = SCAN_PAGE_LAZYFREE;
> + failed_pfn = folio_pfn(folio);
> goto out_unmap;
> }
>
> if (!folio_test_anon(folio)) {
> result = SCAN_PAGE_ANON;
> + failed_pfn = folio_pfn(folio);
> goto out_unmap;
> }
>
> @@ -1721,6 +1724,7 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> if (folio_maybe_mapped_shared(folio)) {
> if (++shared > max_ptes_shared) {
> result = SCAN_EXCEED_SHARED_PTE;
> + failed_pfn = folio_pfn(folio);
> count_collapse_event(HPAGE_PMD_ORDER, THP_SCAN_EXCEED_SHARED_PTE,
> MTHP_STAT_COLLAPSE_EXCEED_SHARED);
> goto out_unmap;
> @@ -1738,15 +1742,18 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> node = folio_nid(folio);
> if (collapse_scan_abort(node, cc)) {
> result = SCAN_SCAN_ABORT;
> + failed_pfn = folio_pfn(folio);
> goto out_unmap;
> }
> cc->node_load[node]++;
> if (!folio_test_lru(folio)) {
> result = SCAN_PAGE_LRU;
> + failed_pfn = folio_pfn(folio);
> goto out_unmap;
> }
> if (folio_test_locked(folio)) {
> result = SCAN_PAGE_LOCK;
> + failed_pfn = folio_pfn(folio);
> goto out_unmap;
> }
>
> @@ -1759,6 +1766,7 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> */
> if (folio_expected_ref_count(folio) != folio_ref_count(folio)) {
> result = SCAN_PAGE_COUNT;
> + failed_pfn = folio_pfn(folio);
> goto out_unmap;
> }
>
> @@ -1782,10 +1790,13 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> unmapped, cc, enabled_orders);
> /* mmap_lock was released above, set lock_dropped */
> *lock_dropped = true;
> - }
> + trace_mm_khugepaged_scan_pmd(mm, -1, referenced, none_or_zero,
> + SCAN_SUCCEED, unmapped);
> + } else {
> out:
> - trace_mm_khugepaged_scan_pmd(mm, folio, referenced,
> - none_or_zero, result, unmapped);
> + trace_mm_khugepaged_scan_pmd(mm, failed_pfn, referenced,
> + none_or_zero, result, unmapped);
> + }
> return result;
> }
>
Same thought
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
--
Cheers,
David
next prev parent reply other threads:[~2026-09-07 12:26 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-28 5:59 [PATCH v4 0/3] mm: khugepaged: fix tracepoint UAF Vernon Yang
2026-08-28 5:59 ` [PATCH v4 1/3] mm: khugepaged: fix swap entry value to folio_pfn() Vernon Yang
2026-09-07 12:25 ` David Hildenbrand (Arm)
2026-09-08 1:35 ` Vernon Yang
2026-09-08 7:39 ` David Hildenbrand (Arm)
2026-08-28 5:59 ` [PATCH v4 2/3] mm: khugepaged: fix folio is used after pte_unmap_unlock() Vernon Yang
2026-09-07 12:26 ` David Hildenbrand (Arm) [this message]
2026-08-28 5:59 ` [PATCH v4 3/3] mm: khugepaged: fix folio is used after folio_put/unlock() Vernon Yang
2026-09-07 12:27 ` David Hildenbrand (Arm)
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=087d76fd-0e1c-485e-bccb-e3ce074439cb@kernel.org \
--to=david@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=baohua@kernel.org \
--cc=dev.jain@arm.com \
--cc=lance.yang@linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=nico.pache@linux.dev \
--cc=ryan.roberts@arm.com \
--cc=stable@vger.kernel.org \
--cc=usama.arif@linux.dev \
--cc=vernon2gm@gmail.com \
--cc=yanglincheng@kylinos.cn \
--cc=zokeefe@google.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.