From nobody Sat Jul 25 16:20:43 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5A34E3CB561; Thu, 16 Jul 2026 08:01:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784188873; cv=none; b=rZXq7RlW7bYYGS72J0AaBRdey6SGsWE9Jm0AedrSAXpRDMdaCoKBpoeWZMQCbEPsVyWvbwpkH6J2ubdF0U5GVbaG6aQOHThO3tIdu2z+Spxa7W9y/R5gJ0UW/k8ZmcuBm3UPq2X5vkyG62m2kdRqg2k2T3S7qE7nkiGOCoZQTB0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784188873; c=relaxed/simple; bh=JUUiPRMxZSwWCYm7c+MtlRsbNPOZXZwPkq6/Pf43/KY=; h=Date:From:To:Subject:Cc:In-Reply-To:References:MIME-Version: Message-ID:Content-Type; b=K4glHvKXeyy/Eclzsu/qkH1Kg4QsDCEqm8vCPYHLcaDSby6FxZ6FKFNmZYvV33FERfn5+I2yN5wMR+V19chiIf/mIkTjh+9x+TANMxL0CNsi52ZQalNf/A2d7o6Uae2gtMPjNO/v0TcbkxcO+6NkzMPP8l2IEmVXJ+u0xhds3s0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=asRVhkKN; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=BpDs98j5; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="asRVhkKN"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="BpDs98j5" Date: Thu, 16 Jul 2026 08:01:07 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1784188869; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZLgvkR71l7xd4akG/r2Ocyybov+3QypyFJxXhWfOpBM=; b=asRVhkKNISA4uN8/gLG0oxpCnM3fHFAomTfRUrfiMbwtNDqj6XGh2NwtBRkGg5yCVUNjnj l7TOgI5aRE6yORbfXq7dzqPQbQAxdQz5F3W+5C17gXD+FP8xuhg1FksrPOQIlYSxFLjuy9 MoOUYbvkW89k7G5iIIOKPt5YXtOI06YYJmdC4tyLYzMzoKq/bNg0jySTLkzGFimBaghJMq YpVqFVHSfTLvVohKhkWSPg/CGRhog6Q71d30jlGARlnz7pDHDrWRpb2CUjKNikiHSv4Fxp FU0F8zECq2wkhJiCRLRS3cbJWB5M8rE8EvuikqV2X35+V7pLuU0K5reKT0zY1A== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1784188869; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ZLgvkR71l7xd4akG/r2Ocyybov+3QypyFJxXhWfOpBM=; b=BpDs98j5TKARORW5jZrmIM8IqQJP1EswVvs1my5eebawHlOaKACZJqLLw1umZXo9fzXNdz 36NouDGz+HabJIAQ== From: "tip-bot2 for Denis V. Lunev" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: x86/mm] x86/mm/pat: Take cpa_lock around large-page collapse Cc: "Denis V. Lunev" , Dave Hansen , "Kiryl Shutsemau (Meta)" , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20260715183453.2381141-1-den@openvz.org> References: <20260715183453.2381141-1-den@openvz.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <178418886773.1844600.15146928511649606123.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Precedence: bulk Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The following commit has been merged into the x86/mm branch of tip: Commit-ID: 1aac65f3e651334259ecb2a5f5ddb81c01f02599 Gitweb: https://git.kernel.org/tip/1aac65f3e651334259ecb2a5f5ddb81c0= 1f02599 Author: Denis V. Lunev AuthorDate: Wed, 15 Jul 2026 20:34:52 +02:00 Committer: Dave Hansen CommitterDate: Wed, 15 Jul 2026 13:06:55 -07:00 x86/mm/pat: Take cpa_lock around large-page collapse Loading and unloading modules concurrently on several CPUs on a KASAN build, with a short delay injected at the CPA page-table lookup to widen the window, faults within minutes: BUG: KASAN: use-after-free in __change_page_attr+0x7cc/0x7e0 Write of size 8 at addr ffff888181139718 by task modprobe ... The buggy address belongs to the physical page: pfn:0x181139 ... page_type: f2(table) cpa_collapse_large_pages() rebuilds a leaf PMD from its 4K PTEs and frees the old PTE-table pages, while __change_page_attr() fetches a PTE pointer from a lockless lookup_address_in_pgd_attr() and writes it with set_pte_atomic() only later. When module text is served from a shared large ROX mapping the two run on the same PMD: CPU A (module load) CPU B (module finalize) ------------------- ----------------------- execmem_make_temp_rw set_memory_nx __change_page_attr split 2M -> 4K table P kpte =3D &P[i] (lockless) execmem_restore_rox set_memory_rox (CPA_COLLAPSE) cpa_collapse_large_pages rebuild leaf PMD flush_tlb_all pagetable_free(P) set_pte_atomic(kpte, ...) -> writes into freed P P is a page-table page (page_type: table), reused at once, so the write corrupts whatever got the page next: a bad-pte or bad-page splat, or a fatal fault once P has been turned into read-only text. The flush_tlb_all() before the free does not close this: its IPI only serializes against page-table walkers that run with interrupts off (e.g. GUP-fast); the walk in __change_page_attr() runs with interrupts on, so nothing stops it from holding a stale pointer into P. Serialize the collapse - the PMD rebuild, TLB flush and PTE-table free - under cpa_lock, the same lock __change_page_attr() now takes unconditionally since commit ("x86/mm/pat: stop gating cpa_lock on debug_pagealloc_enabled()"), so a concurrent walker can no longer hold a pointer into a table the collapse is about to free. Fixes: 41d88484c71c ("x86/mm/pat: restore large ROX pages after fragmentati= on") Signed-off-by: Denis V. Lunev Signed-off-by: Dave Hansen Acked-by: Kiryl Shutsemau (Meta) Link: https://patch.msgid.link/20260715183453.2381141-1-den@openvz.org --- arch/x86/mm/pat/set_memory.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c index e9b4083..b1e780a 100644 --- a/arch/x86/mm/pat/set_memory.c +++ b/arch/x86/mm/pat/set_memory.c @@ -417,6 +417,8 @@ static void cpa_collapse_large_pages(struct cpa_data *c= pa) int collapsed =3D 0; int i; =20 + spin_lock(&cpa_lock); + if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) { for (i =3D 0; i < cpa->numpages; i++) collapsed +=3D collapse_large_pages(__cpa_addr(cpa, i), @@ -430,8 +432,10 @@ static void cpa_collapse_large_pages(struct cpa_data *= cpa) collapsed +=3D collapse_large_pages(addr, &pgtables); } =20 - if (!collapsed) + if (!collapsed) { + spin_unlock(&cpa_lock); return; + } =20 flush_tlb_all(); =20 @@ -439,6 +443,8 @@ static void cpa_collapse_large_pages(struct cpa_data *c= pa) list_del(&ptdesc->pt_list); pagetable_free(ptdesc); } + + spin_unlock(&cpa_lock); } =20 static void cpa_flush(struct cpa_data *cpa, int cache)