From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out-180.mta1.migadu.com (out-180.mta1.migadu.com [95.215.58.180]) (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 8978E41611C for ; Tue, 7 Jul 2026 13:17:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.180 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783430247; cv=none; b=efqAcjxlUcl6iWKLcCkIEORIIQCn1wsMPCeo1vOu39GhrOwWPlzZ18tERHO9LmpTaXrc/rOoJdd2H+36ObDQ8KzxvBMLTDhQxp6tQLyLR9Tg5DFvW4lTDeS/ZR/gdaAj1p+J82ZJHz9vyB/tKKngYmIOY130IpNZ3Oln03xdDUI= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783430247; c=relaxed/simple; bh=BZqD0n4fm6T/1cYJskF4/37O//DRC1YFFkUBjY6JTOc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YxUPrhIcj84fXs35zGIN21T/AWKu4UKEkBB50sjEYuPU3sVh2f1ooFE1ax0zD3AT0995DwTESX+bV1bpov0NtXAtzlaMhWXGqRpUPpk3ImqTLxJJmEPF5PrQXDtuUmp7Sa/YHoxesUAwjPxwAvChVOWgqgksdGfURkXvrKxK8gE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=uyVahiJw; arc=none smtp.client-ip=95.215.58.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="uyVahiJw" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1783430243; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uXqxsT2REYcN58ckChjdU8/v9QTtwid7lase85JBTGA=; b=uyVahiJwyDi3GxwsD9aKVkH9twZUpL0EMKPBoUMClVlHBHnGpBmgLuAjpqTC6M0xvYGh6V 8Cilb7uKUD0vtYJBXCMwEPpX0QkdZhChuJg/yt1Vq2Ev9f6qaV1RqTHZdCoUfEm0BqnNDR BEHoqWn70c7b+Rc59aA+EPeXJU4SWQU= From: Usama Arif To: Xueyuan Chen Cc: Usama Arif , Andrew Morton , David Hildenbrand , Catalin Marinas , Will Deacon , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, linux-mm@kvack.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Lance Yang , Jann Horn , Yang Shi , Mike Rapoport , Lorenzo Stoakes , Zi Yan , Baolin Wang , "Liam R . Howlett" , Nico Pache , Ryan Roberts , Dev Jain , Barry Song , "H . Peter Anvin" , Andy Lutomirski , Peter Zijlstra Subject: Re: [RFC PATCH v3 1/3] mm: make persistent huge zero folio read-only Date: Tue, 7 Jul 2026 06:17:12 -0700 Message-ID: <20260707131714.3266156-1-usama.arif@linux.dev> In-Reply-To: <20260706130440.9295-2-xueyuan.chen21@gmail.com> References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT On Mon, 6 Jul 2026 21:04:38 +0800 Xueyuan Chen wrote: > From: Xueyuan Chen > > The persistent huge zero folio is shared globally and should stay zero > after initialization. As Jann Horn pointed out[1], kernel bugs have ended > up writing to pages that were meant to be read-only, including in > security-sensitive cases. Making the persistent huge zero folio read-only > in the direct map turns such writes into faults instead of silent zero-page > corruption. > > Add set_direct_map_ro_noflush() so mm code can make a direct-map range > read-only. Use an address-based signature to match ongoing direct-map > helper work[2], where existing page-based helpers may move the same way. > The helper is direct-map specific and does not flush TLBs. Architectures > without direct-map permission support keep existing behavior through the > generic stub. > > Persistent huge zero folio setup happens during early boot, so no explicit > TLB flush is needed. > > Inspired by Jann Horn's read-only zero page work[1] and follow-up > discussion[3] with Yang Shi. > > [1] https://lore.kernel.org/linux-mm/20260508-ro-zeropage-v1-1-9808abc20b49@google.com/ > [2] https://lore.kernel.org/linux-mm/0e5b23a6-4895-454a-9dfa-6dc21adc2991@kernel.org/ > [3] https://lore.kernel.org/linux-mm/CAHbLzkrXXe7r3n3jXgDKtwZhRqj=jDx9E6dLOULohnhBguvi9A@mail.gmail.com/ > > Suggested-by: David Hildenbrand > Co-developed-by: Lance Yang > Signed-off-by: Lance Yang > Signed-off-by: Xueyuan Chen > --- > include/linux/set_memory.h | 26 ++++++++++++++++++++++++++ > mm/huge_memory.c | 9 ++++++++- > 2 files changed, 34 insertions(+), 1 deletion(-) > > diff --git a/include/linux/set_memory.h b/include/linux/set_memory.h > index 3030d9245f5a..a905074fb21d 100644 > --- a/include/linux/set_memory.h > +++ b/include/linux/set_memory.h > @@ -40,6 +40,22 @@ static inline int set_direct_map_valid_noflush(struct page *page, > return 0; > } > > +/** > + * set_direct_map_ro_noflush - make direct-map mappings read-only > + * @addr: start address in the direct map > + * @nr_pages: number of pages starting at @addr > + * > + * Make the direct-map mappings for @nr_pages pages starting at @addr > + * read-only, without flushing TLBs. > + * > + * Return: 0 on success or when unsupported, negative error code on failure. > + */ > +static inline int set_direct_map_ro_noflush(const void *addr, > + unsigned long nr_pages) > +{ > + return 0; > +} > + > static inline bool kernel_page_present(struct page *page) > { > return true; > @@ -56,6 +72,16 @@ static inline bool can_set_direct_map(void) > } > #define can_set_direct_map can_set_direct_map > #endif > + > +#ifndef set_direct_map_ro_noflush > +static inline int set_direct_map_ro_noflush(const void *addr, > + unsigned long nr_pages) > +{ > + return 0; > +} > + > +#define set_direct_map_ro_noflush set_direct_map_ro_noflush > +#endif > #endif /* CONFIG_ARCH_HAS_SET_DIRECT_MAP */ > > #ifdef CONFIG_X86_64 > diff --git a/mm/huge_memory.c b/mm/huge_memory.c > index bdd8635922f9..6633217b10dc 100644 > --- a/mm/huge_memory.c > +++ b/mm/huge_memory.c > @@ -41,6 +41,7 @@ > #include > #include > #include > +#include > > #include > #include "internal.h" > @@ -981,8 +982,14 @@ static int __init thp_shrinker_init(void) > * that get_huge_zero_folio() will most likely not fail as > * thp_shrinker_init() is invoked early on during boot. > */ > - if (!get_huge_zero_folio()) > + if (!get_huge_zero_folio()) { > pr_warn("Allocating persistent huge zero folio failed\n"); > + return 0; > + } > + > + /* Set up during early boot; no explicit TLB flush is needed here. */ > + set_direct_map_ro_noflush(folio_address(huge_zero_folio), > + HPAGE_PMD_NR); Hi, Can this really skip the TLB flush here? This runs from a subsys_initcall, after smp_init() and after the folio was allocated and zeroed through the writable direct map. The noflush helper updates the direct-map PTEs but does not invalidate stale writable kernel TLB entries. I think we need a TLB flush here? > return 0; > } > > -- > 2.49.0 > >