From: Jiri Slaby <jirislaby@kernel.org>
To: linux-kernel@vger.kernel.org, linux-tip-commits@vger.kernel.org
Cc: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>,
"Mike Rapoport (Microsoft)" <rppt@kernel.org>,
Dave Hansen <dave.hansen@linux.intel.com>,
Atish Patra <atishp@meta.com>, Nikunj A Dadhania <nikunj@amd.com>,
stable@vger.kernel.org, x86@kernel.org
Subject: Re: [tip: x86/urgent] x86/mm/pat: Acquire init_mm read lock on attribute change to avoid UAF
Date: Tue, 1 Sep 2026 08:05:07 +0200 [thread overview]
Message-ID: <ea12e0a4-36b3-4c71-8930-72fc4eaf369f@kernel.org> (raw)
In-Reply-To: <178821524648.3717435.13938325908577682845.tip-bot2@tip-bot2>
On 01. 09. 26, 0:27, tip-bot2 for Lorenzo Stoakes (ARM) wrote:
> The following commit has been merged into the x86/urgent branch of tip:
>
> Commit-ID: 477cf5cd1f698053df7426b7b8d9339e85e00946
> Gitweb: https://git.kernel.org/tip/477cf5cd1f698053df7426b7b8d9339e85e00946
> Author: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> AuthorDate: Thu, 13 Aug 2026 12:01:25 +03:00
> Committer: Dave Hansen <dave.hansen@linux.intel.com>
> CommitterDate: Mon, 31 Aug 2026 15:15:42 -07:00
>
> x86/mm/pat: Acquire init_mm read lock on attribute change to avoid UAF
>
> A previous commit protected against races between ptdump and CPA collapse,
> however one still exists between attribute changes and collapse as reported
> by Denis V. Lunev (linked).
>
> When an attribute change arises, a lockless page table walker obtains a PTE
> entry, which is later written to via set_pte_atomic():
>
> ...
> -> change_page_attr_set_clr()
> -> __change_page_attr_set_clr()
> -> __change_page_attr()
> -> _lookup_address_cpa()
> -> lookup_address_in_pgd_attr()
> -> [ lockless page table walker ]
> -> set_pte_atomic()
>
> There is nothing preventing a concurrent CPA collapse which can free the
> PTE that was retrieved here, resulting in a use-after-free.
>
> With the mmap write lock taken on init_mm over CPA collapse, resolve this
> race by acquiring an mmap read lock on init_mm over
> __change_page_attr_set_clr().
>
> This locks across the whole operation over which the walk and the PTE entry
> write occurs, solving the race.
>
> It is safe to do this here, as no spinlocks are held upon entry to
> __change_page_attr_set_clr().
>
> However, the lock must not be held over an allocation, as allocation can
> trigger reclaim and shrinkers may call into CPA recursively, making
> deadlocks possible (init_mm -> ... -> fs_reclaim -> init_mm).
>
> A page table is allocated when a huge page needs to be split:
>
> -> change_page_attr_set_clr()
> -> __change_page_attr_set_clr()
> -> __change_page_attr()
> -> split_large_page()
> [ pagetable_alloc() ]
> -> __split_large_page()
>
> Avoid deadlocks by dropping the mmap lock across pagetable_alloc() in
> split_large_page() and track whether this is needed by adding a new
> 'init_mm_read_locked' flag to struct cpa_data.
>
> This is safe as __split_large_page() (called with locks re-established)
> revalidates that the page table entry is the same as it was prior to the
> locks being dropped and __change_page_attr() repeats the entire page table
> walk whenever a split occurs, so concurrent split and collapse are
> accounted for.
>
> Concurrent ptdump is also safe as the lock is only dropped over page table
> allocation during which time the page table has not yet been modified.
>
> The CPA_COLLAPSE flag is only set by set_memory_rox(), which exclusively
> operates upon vmalloc ranges, and on x86 only within the module mapping
> space.
>
> This is important, because some callers directly invoke
> __change_page_attr_set_clr(), bypassing this lock. However, none of these
> operate within the module mapping space.
>
> * cpa_process_alias() - a recursive helper called by
> __change_page_attr_set_clr().
> * __set_memory_enc_pgtable() - operates on the direct mapping and (via
> __vmbus_establish_gpadl()) the vmalloc mapping space.
> * __set_pages_[n]p() - called by set_direct_map_[invalid, default,
> valid]_noflush(), __kernel_map_pages() - operates on the direct map.
> * kernel_[un]map_pages_in_pgd() - operates on EFI ranges.
>
> This work is based upon Denis V. Lunev's excellent analysis of the bug with
> gratitude.
>
> Fixes: 41d88484c71c ("x86/mm/pat: restore large ROX pages after fragmentation")
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
> Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
> Tested-by: Atish Patra <atishp@meta.com>
> Tested-by: Nikunj A Dadhania <nikunj@amd.com>
> Link: https://lore.kernel.org/all/20260626163213.2284080-1-den@openvz.org/
> Cc:stable@vger.kernel.org
> Link: https://patch.msgid.link/20260813-cpa-fixes-v2-2-39b4ff90f91d@kernel.org
> ---
> arch/x86/mm/pat/set_memory.c | 28 +++++++++++++++++++++++++---
> 1 file changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
> index c38faf3..cb5d6d6 100644
> --- a/arch/x86/mm/pat/set_memory.c
> +++ b/arch/x86/mm/pat/set_memory.c
> @@ -22,6 +22,7 @@
> #include <linux/cc_platform.h>
> #include <linux/set_memory.h>
> #include <linux/memregion.h>
> +#include <linux/cleanup.h>
>
> #include <asm/e820/api.h>
> #include <asm/processor.h>
> @@ -49,7 +50,8 @@ struct cpa_data {
> unsigned int flags;
> unsigned int force_split : 1,
> force_static_prot : 1,
> - force_flush_all : 1;
> + force_flush_all : 1,
> + init_mm_read_locked : 1;
> struct page **pages;
> };
>
> @@ -409,7 +411,7 @@ static void __cpa_flush_tlb(void *data)
>
> static int collapse_large_pages(unsigned long addr, struct list_head *pgtables);
>
> -static void cpa_collapse_large_pages(struct cpa_data *cpa)
> +static void __cpa_collapse_large_pages(struct cpa_data *cpa)
> {
> unsigned long start, addr, end;
> struct ptdesc *ptdesc, *tmp;
> @@ -443,6 +445,18 @@ static void cpa_collapse_large_pages(struct cpa_data *cpa)
> }
> }
>
> +static void cpa_collapse_large_pages(struct cpa_data *cpa)
> +{
> + /*
> + * Take the mmap write lock on init_mm to:
> + * - Avoid a use-after-free if raced by ptdump (which takes its own
> + * write lock on init_mm).
> + * - Serialise concurrent CPA walkers.
> + */
> + scoped_guard(mmap_write_lock, &init_mm)
> + __cpa_collapse_large_pages(cpa);
> +}
> +
Ah, this belongs to the "Acquire init_mm *write* lock" counterpart. Not
sure how you managed to split/combine these two 8-).
thanks,
--
js
suse labs
next prev parent reply other threads:[~2026-09-01 6:05 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-13 9:01 [PATCH v2 0/5] x86/mm/pat: CPA fixes Mike Rapoport
2026-08-13 9:01 ` [PATCH v2 1/5] x86/mm/pat: acquire init_mm write lock on collapse to avoid UAF Mike Rapoport
2026-08-31 22:27 ` [tip: x86/urgent] x86/mm/pat: Acquire " tip-bot2 for Lorenzo Stoakes (ARM)
2026-09-01 6:03 ` Jiri Slaby
2026-09-01 7:10 ` Lorenzo Stoakes (ARM)
2026-09-01 23:36 ` Dave Hansen
2026-09-02 6:53 ` Lorenzo Stoakes (ARM)
2026-09-02 18:33 ` tip-bot2 for Lorenzo Stoakes (ARM)
2026-08-13 9:01 ` [PATCH v2 2/5] x86/mm/pat: acquire init_mm read lock on attribute change " Mike Rapoport
2026-08-31 22:27 ` [tip: x86/urgent] x86/mm/pat: Acquire " tip-bot2 for Lorenzo Stoakes (ARM)
2026-09-01 6:05 ` Jiri Slaby [this message]
2026-09-01 7:20 ` Lorenzo Stoakes (ARM)
2026-09-01 13:46 ` Dave Hansen
2026-09-02 18:33 ` tip-bot2 for Lorenzo Stoakes (ARM)
2026-08-13 9:01 ` [PATCH v2 3/5] x86/alternative: exclude text poking against change_page_attr() Mike Rapoport
2026-08-25 9:37 ` Jiri Slaby
2026-08-31 22:27 ` [tip: x86/urgent] x86/alternative: Exclude " tip-bot2 for Pedro Falcato
2026-09-01 6:16 ` Jiri Slaby
2026-09-01 7:18 ` Lorenzo Stoakes (ARM)
2026-09-01 7:22 ` Jiri Slaby
2026-09-01 7:24 ` Lorenzo Stoakes (ARM)
2026-09-02 18:33 ` tip-bot2 for Pedro Falcato
2026-08-13 9:01 ` [PATCH v2 4/5] x86/mm/pat: allocate split page tables as kernel page tables Mike Rapoport
2026-08-31 22:27 ` [tip: x86/urgent] x86/mm/pat: Allocate " tip-bot2 for Lorenzo Stoakes (ARM)
2026-09-02 18:33 ` tip-bot2 for Lorenzo Stoakes (ARM)
2026-08-13 9:01 ` [PATCH v2 5/5] x86/mm/pat: fix effective RW computation in lookup_address_in_pgd_attr() Mike Rapoport (Microsoft)
2026-08-13 9:45 ` Lorenzo Stoakes (ARM)
2026-08-31 22:27 ` [tip: x86/urgent] x86/mm/pat: Fix " tip-bot2 for Mike Rapoport (Microsoft)
2026-09-02 18:33 ` tip-bot2 for Mike Rapoport (Microsoft)
2026-09-05 4:42 ` Nathan Chancellor
2026-08-13 15:05 ` [PATCH v2 0/5] x86/mm/pat: CPA fixes Nikunj A. Dadhania
2026-08-13 15:07 ` Lorenzo Stoakes (ARM)
2026-08-13 15:23 ` Pedro Falcato
2026-08-13 17:13 ` Andrew Morton
2026-08-25 7:12 ` Atish Patra
2026-08-25 7:31 ` Lorenzo Stoakes (ARM)
2026-08-25 20:05 ` Atish Patra
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=ea12e0a4-36b3-4c71-8930-72fc4eaf369f@kernel.org \
--to=jirislaby@kernel.org \
--cc=atishp@meta.com \
--cc=dave.hansen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tip-commits@vger.kernel.org \
--cc=ljs@kernel.org \
--cc=nikunj@amd.com \
--cc=rppt@kernel.org \
--cc=stable@vger.kernel.org \
--cc=x86@kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®