* [RFC PATCH v2 0/3] make persistent huge zero folio read-only
@ 2026-06-09 14:37 Xueyuan Chen
2026-06-09 14:37 ` [RFC PATCH v2 1/3] mm/huge_memory: " Xueyuan Chen
` (2 more replies)
0 siblings, 3 replies; 14+ messages in thread
From: Xueyuan Chen @ 2026-06-09 14:37 UTC (permalink / raw)
To: akpm, linux-mm
Cc: linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx,
mingo, bp, dave.hansen, luto, peterz, hpa, david, ljs, liam,
vbabka, rppt, surenb, mhocko, ziy, baolin.wang, npache,
ryan.roberts, dev.jain, baohua, lance.yang, yang, jannh,
Xueyuan Chen
Hi all,
This series makes the persistent huge zero folio read-only in the direct
map where the architecture can support it.
The motivation comes from Jann Horn's read-only zero page work[1] and the
follow-up discussion[2] with Yang Shi. As Jann pointed out, the kernel has
had bugs, including security bugs, where pages taken with read-only
semantics were later written to. For the huge zero folio, making the direct
map read-only turns such writes into faults instead of silently corrupting
shared zero contents.
Patch 1 adds a generic arch_make_pages_readonly() hook and uses it after
the persistent huge zero folio is allocated. Patches 2 and 3 implement the
hook for arm64 and x86.
If the hook is not implemented, or the architecture cannot safely update
the mapping, the existing writable mapping is left in place.
[1] https://lore.kernel.org/linux-mm/20260508-ro-zeropage-v1-1-9808abc20b49@google.com/
[2] https://lore.kernel.org/linux-mm/CAHbLzkrXXe7r3n3jXgDKtwZhRqj=jDx9E6dLOULohnhBguvi9A@mail.gmail.com/
RFC v1 -> RFC v2:
- Patch #01: Drop the READONLY_HUGE_ZERO_FOLIO Kconfig option
(per Dave, thanks!).
- Patch #01: Replace the huge-zero-folio-specific hook with a generic
page-range hook (per David, thanks!)
- Patch #02 and #03: Update the arm64 and x86 implementations for the new
hook.
- https://lore.kernel.org/linux-mm/20260527035607.14919-1-xueyuan.chen21@gmail.com/
Xueyuan Chen (3):
mm/huge_memory: make persistent huge zero folio read-only
arm64/mm: make pages read-only in the linear map
x86/mm: make pages read-only in the direct map
arch/arm64/mm/pageattr.c | 13 +++++++++++++
arch/x86/mm/init.c | 9 +++++++++
include/linux/mm.h | 2 ++
mm/huge_memory.c | 13 ++++++++++++-
4 files changed, 36 insertions(+), 1 deletion(-)
--
2.47.3
^ permalink raw reply [flat|nested] 14+ messages in thread* [RFC PATCH v2 1/3] mm/huge_memory: make persistent huge zero folio read-only 2026-06-09 14:37 [RFC PATCH v2 0/3] make persistent huge zero folio read-only Xueyuan Chen @ 2026-06-09 14:37 ` Xueyuan Chen 2026-06-09 19:33 ` Dave Hansen 2026-06-09 19:45 ` Andrew Morton 2026-06-09 14:38 ` [RFC PATCH v2 2/3] arm64/mm: make pages read-only in the linear map Xueyuan Chen 2026-06-09 14:38 ` [RFC PATCH v2 3/3] x86/mm: make pages read-only in the direct map Xueyuan Chen 2 siblings, 2 replies; 14+ messages in thread From: Xueyuan Chen @ 2026-06-09 14:37 UTC (permalink / raw) To: akpm, linux-mm Cc: linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, david, ljs, liam, vbabka, rppt, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, lance.yang, yang, jannh, Xueyuan Chen, Dave Hansen The huge zero folio is shared globally, and its contents should never change after initialization. As Jann Horn pointed out[1], the kernel has had bugs, including security bugs, where read-only pages were later written to. If the persistent huge zero folio is read-only in the direct map, such writes fault instead of silently corrupting the shared zero contents. Add arch_make_pages_readonly() so mm code can request read-only direct-map protection for a page range. Direct-map protection is architecture-specific, so the generic weak implementation does nothing. This was inspired by Jann Horn's read-only zero page work[1] and follow-up discussion[2] 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/CAHbLzkrXXe7r3n3jXgDKtwZhRqj=jDx9E6dLOULohnhBguvi9A@mail.gmail.com/ Suggested-by: Dave Hansen <dave.hansen@intel.com> Suggested-by: David Hildenbrand <david@kernel.org> Co-developed-by: Lance Yang <lance.yang@linux.dev> Signed-off-by: Lance Yang <lance.yang@linux.dev> Signed-off-by: Xueyuan Chen <xueyuan.chen21@gmail.com> --- include/linux/mm.h | 2 ++ mm/huge_memory.c | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 0f2612a70fb1..02d33cf45b01 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2936,6 +2936,8 @@ static inline int arch_make_folio_accessible(struct folio *folio) } #endif +bool arch_make_pages_readonly(struct page *page, int nr_pages); + /* * Some inline functions in vmstat.h depend on page_zone() */ diff --git a/mm/huge_memory.c b/mm/huge_memory.c index b81d1ecb434b..2e9d01dc1197 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -308,6 +308,11 @@ static unsigned long shrink_huge_zero_folio_scan(struct shrinker *shrink, return 0; } +bool __weak arch_make_pages_readonly(struct page *page, int nr_pages) +{ + return false; +} + static struct shrinker *huge_zero_folio_shrinker; #ifdef CONFIG_SYSFS @@ -982,8 +987,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; + } + + arch_make_pages_readonly(folio_page(huge_zero_folio, 0), + HPAGE_PMD_NR); + return 0; } -- 2.47.3 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/3] mm/huge_memory: make persistent huge zero folio read-only 2026-06-09 14:37 ` [RFC PATCH v2 1/3] mm/huge_memory: " Xueyuan Chen @ 2026-06-09 19:33 ` Dave Hansen 2026-06-10 3:20 ` Lance Yang 2026-06-09 19:45 ` Andrew Morton 1 sibling, 1 reply; 14+ messages in thread From: Dave Hansen @ 2026-06-09 19:33 UTC (permalink / raw) To: Xueyuan Chen, akpm, linux-mm Cc: linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, david, ljs, liam, vbabka, rppt, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, lance.yang, yang, jannh On 6/9/26 07:37, Xueyuan Chen wrote: > +bool __weak arch_make_pages_readonly(struct page *page, int nr_pages) > +{ > + return false; > +} This is a rather wonky function. It's going to cause all kinds of fun if it is used like this: arch_make_pages_readonly(syscall_table, 1); It's also kinda weird to have it return a bool, and not check that bool at the single call site. Some things come to mind: 1. This function needs commenting. It needs to say what it does, when architectures should override it and what their implementations should look like. It needs to be clear that this can't be used for anything really important. What should architectures do with alias mappings? Are they allowed to touch non-direct map aliases? Are they required to? 2. The return type needs to be reconsidered. Is 'bool' even acceptable? Should it just be 'void' if callers can't do anything when it fails? 3. What should the naming be? "readonly" vs "ro". Should it have a "maybe" since it's kinda optional? 4. Should this new API be folio or page-based in the first place? 5. Is mm/huge_memory.c the right place to define a generic mm function, even a stub? ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/3] mm/huge_memory: make persistent huge zero folio read-only 2026-06-09 19:33 ` Dave Hansen @ 2026-06-10 3:20 ` Lance Yang 2026-06-11 6:49 ` Mike Rapoport 0 siblings, 1 reply; 14+ messages in thread From: Lance Yang @ 2026-06-10 3:20 UTC (permalink / raw) To: dave.hansen Cc: xueyuan.chen21, akpm, linux-mm, linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, david, ljs, liam, vbabka, rppt, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, lance.yang, yang, jannh Hi Dave, Thanks for taking the time to review. On Tue, Jun 09, 2026 at 12:33:36PM -0700, Dave Hansen wrote: >On 6/9/26 07:37, Xueyuan Chen wrote: >> +bool __weak arch_make_pages_readonly(struct page *page, int nr_pages) >> +{ >> + return false; >> +} > >This is a rather wonky function. It's going to cause all kinds of fun if >it is used like this: > > arch_make_pages_readonly(syscall_table, 1); Ouch, yeah, it is ... >It's also kinda weird to have it return a bool, and not check that bool >at the single call site. Some things come to mind: > >1. This function needs commenting. It needs to say what it does, when > architectures should override it and what their implementations > should look like. It needs to be clear that this can't be used for > anything really important. What should architectures do with alias > mappings? Are they allowed to touch non-direct map aliases? Are they > required to? Agreed. Needs a real comment ... Just meant as a best-effort direct/linear-map permission chang, nothing stronger than that. I should spell out what happens, or does not happen, to non-direct-map aliases, if anything, and make clear callers cannot treat this as a hard guarantee :D >2. The return type needs to be reconsidered. Is 'bool' even acceptable? > Should it just be 'void' if callers can't do anything when it fails? Maybe ignoring it is OK now, but someone may need the return value later? >3. What should the naming be? "readonly" vs "ro". Should it have a > "maybe" since it's kinda optional? Fair point. "make" may be overstating it a bit ... With a return value, arch_try_make_pages_readonly() sounds about right to me. If we end up with void and pure best-effort semantics, maybe arch_maybe_make_pages_readonly() fits better :) >4. Should this new API be folio or page-based in the first place? For page vs folio, I was mostly following David's RFC v1 suggestion. Current caller is a folio, sure, but the page-range helper leaves room for non-folio users later. Happy to add a simple folio wrapper if that reads better ;) >5. Is mm/huge_memory.c the right place to define a generic mm function, > even a stub? Ah, you're right! My bad, wrong place for a generic stub. Will move it out for RFC v3. Thanks, Lance ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/3] mm/huge_memory: make persistent huge zero folio read-only 2026-06-10 3:20 ` Lance Yang @ 2026-06-11 6:49 ` Mike Rapoport 2026-06-11 10:35 ` Lance Yang 0 siblings, 1 reply; 14+ messages in thread From: Mike Rapoport @ 2026-06-11 6:49 UTC (permalink / raw) To: Lance Yang Cc: dave.hansen, xueyuan.chen21, akpm, linux-mm, linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, david, ljs, liam, vbabka, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, yang, jannh Hi, On Wed, Jun 10, 2026 at 11:20:22AM +0800, Lance Yang wrote: > Hi Dave, > > Thanks for taking the time to review. > > On Tue, Jun 09, 2026 at 12:33:36PM -0700, Dave Hansen wrote: > >On 6/9/26 07:37, Xueyuan Chen wrote: > >> +bool __weak arch_make_pages_readonly(struct page *page, int nr_pages) > >> +{ > >> + return false; > >> +} > > > >This is a rather wonky function. It's going to cause all kinds of fun if > >it is used like this: > > > > arch_make_pages_readonly(syscall_table, 1); > > Ouch, yeah, it is ... We already have set_direct_map* APIs, why don't you add a new one there? set_direct_map_ro() for example. > >It's also kinda weird to have it return a bool, and not check that bool > >at the single call site. Some things come to mind: > > > >1. This function needs commenting. It needs to say what it does, when > > architectures should override it and what their implementations > > should look like. It needs to be clear that this can't be used for > > anything really important. What should architectures do with alias > > mappings? Are they allowed to touch non-direct map aliases? Are they > > required to? > > Agreed. Needs a real comment ... > > Just meant as a best-effort direct/linear-map permission chang, nothing > stronger than that. I should spell out what happens, or does not happen, > to non-direct-map aliases, if anything, and make clear callers cannot > treat this as a hard guarantee :D It's not only about highmem, anything that changes the direct map might fail to allocate memory when splitting larger mappings. > >2. The return type needs to be reconsidered. Is 'bool' even acceptable? > > Should it just be 'void' if callers can't do anything when it fails? > > Maybe ignoring it is OK now, but someone may need the return value later? > > >3. What should the naming be? "readonly" vs "ro". Should it have a > > "maybe" since it's kinda optional? > > Fair point. "make" may be overstating it a bit ... > > With a return value, arch_try_make_pages_readonly() sounds about right > to me. If we end up with void and pure best-effort semantics, maybe > arch_maybe_make_pages_readonly() fits better :) Realistically, I wouldn't expect 32-bit configs to enable PERSISTENT_HUGE_ZERO_FOLIO or even THP, so naming this function to reflect 32-bit behaviour seems odd going forward. > >4. Should this new API be folio or page-based in the first place? > > For page vs folio, I was mostly following David's RFC v1 suggestion. > > Current caller is a folio, sure, but the page-range helper leaves room > for non-folio users later. Happy to add a simple folio wrapper if that > reads better ;) > > >5. Is mm/huge_memory.c the right place to define a generic mm function, > > even a stub? > > Ah, you're right! My bad, wrong place for a generic stub. Will move it > out for RFC v3. We have include/linux/set_memory.h for such function declarations and their stubs. > Thanks, Lance > -- Sincerely yours, Mike. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/3] mm/huge_memory: make persistent huge zero folio read-only 2026-06-11 6:49 ` Mike Rapoport @ 2026-06-11 10:35 ` Lance Yang 0 siblings, 0 replies; 14+ messages in thread From: Lance Yang @ 2026-06-11 10:35 UTC (permalink / raw) To: rppt Cc: lance.yang, dave.hansen, xueyuan.chen21, akpm, linux-mm, linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, david, ljs, liam, vbabka, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, yang, jannh On Thu, Jun 11, 2026 at 09:49:22AM +0300, Mike Rapoport wrote: >Hi, Hi, > >On Wed, Jun 10, 2026 at 11:20:22AM +0800, Lance Yang wrote: >> Hi Dave, >> >> Thanks for taking the time to review. >> >> On Tue, Jun 09, 2026 at 12:33:36PM -0700, Dave Hansen wrote: >> >On 6/9/26 07:37, Xueyuan Chen wrote: >> >> +bool __weak arch_make_pages_readonly(struct page *page, int nr_pages) >> >> +{ >> >> + return false; >> >> +} >> > >> >This is a rather wonky function. It's going to cause all kinds of fun if >> >it is used like this: >> > >> > arch_make_pages_readonly(syscall_table, 1); >> >> Ouch, yeah, it is ... > >We already have set_direct_map* APIs, why don't you add a new one there? >set_direct_map_ro() for example. Good point. I was trying to make this generic, but that's a bit too cute. This is really a direct-map thing, so adding a set_direct_map_ro() helper there makes more sense. > >> >It's also kinda weird to have it return a bool, and not check that bool >> >at the single call site. Some things come to mind: >> > >> >1. This function needs commenting. It needs to say what it does, when >> > architectures should override it and what their implementations >> > should look like. It needs to be clear that this can't be used for >> > anything really important. What should architectures do with alias >> > mappings? Are they allowed to touch non-direct map aliases? Are they >> > required to? >> >> Agreed. Needs a real comment ... >> >> Just meant as a best-effort direct/linear-map permission chang, nothing >> stronger than that. I should spell out what happens, or does not happen, >> to non-direct-map aliases, if anything, and make clear callers cannot >> treat this as a hard guarantee :D > >It's not only about highmem, anything that changes the direct map might >fail to allocate memory when splitting larger mappings. Yes, exactly. > >> >2. The return type needs to be reconsidered. Is 'bool' even acceptable? >> > Should it just be 'void' if callers can't do anything when it fails? >> >> Maybe ignoring it is OK now, but someone may need the return value later? >> >> >3. What should the naming be? "readonly" vs "ro". Should it have a >> > "maybe" since it's kinda optional? >> >> Fair point. "make" may be overstating it a bit ... >> >> With a return value, arch_try_make_pages_readonly() sounds about right >> to me. If we end up with void and pure best-effort semantics, maybe >> arch_maybe_make_pages_readonly() fits better :) > >Realistically, I wouldn't expect 32-bit configs to enable >PERSISTENT_HUGE_ZERO_FOLIO or even THP, so naming this function to reflect >32-bit behaviour seems odd going forward. Cool with that, if no one objects. No need to bake that into the name I guess. int return plus a comment should be enough, just like set_direct_map_*() family already does :) >> >4. Should this new API be folio or page-based in the first place? >> >> For page vs folio, I was mostly following David's RFC v1 suggestion. >> >> Current caller is a folio, sure, but the page-range helper leaves room >> for non-folio users later. Happy to add a simple folio wrapper if that >> reads better ;) >> >> >5. Is mm/huge_memory.c the right place to define a generic mm function, >> > even a stub? >> >> Ah, you're right! My bad, wrong place for a generic stub. Will move it >> out for RFC v3. > >We have include/linux/set_memory.h for such function declarations and their >stubs. Yep, will move it there :) Thanks, Lance ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/3] mm/huge_memory: make persistent huge zero folio read-only 2026-06-09 14:37 ` [RFC PATCH v2 1/3] mm/huge_memory: " Xueyuan Chen 2026-06-09 19:33 ` Dave Hansen @ 2026-06-09 19:45 ` Andrew Morton 2026-06-10 2:15 ` Lance Yang 1 sibling, 1 reply; 14+ messages in thread From: Andrew Morton @ 2026-06-09 19:45 UTC (permalink / raw) To: Xueyuan Chen Cc: linux-mm, linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, david, ljs, liam, vbabka, rppt, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, lance.yang, yang, jannh, Dave Hansen On Tue, 9 Jun 2026 22:37:59 +0800 Xueyuan Chen <xueyuan.chen21@gmail.com> wrote: > The huge zero folio is shared globally, and its contents should never > change after initialization. As Jann Horn pointed out[1], the kernel has > had bugs, including security bugs, where read-only pages were later written > to. If the persistent huge zero folio is read-only in the direct map, such > writes fault instead of silently corrupting the shared zero contents. > > Add arch_make_pages_readonly() so mm code can request read-only direct-map > protection for a page range. Direct-map protection is > architecture-specific, so the generic weak implementation does nothing. > > This was inspired by Jann Horn's read-only zero page work[1] and follow-up > discussion[2] 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/CAHbLzkrXXe7r3n3jXgDKtwZhRqj=jDx9E6dLOULohnhBguvi9A@mail.gmail.com/ > > ... > > --- a/mm/huge_memory.c > +++ b/mm/huge_memory.c > @@ -308,6 +308,11 @@ static unsigned long shrink_huge_zero_folio_scan(struct shrinker *shrink, > return 0; > } > > +bool __weak arch_make_pages_readonly(struct page *page, int nr_pages) > +{ > + return false; > +} > + > static struct shrinker *huge_zero_folio_shrinker; > > #ifdef CONFIG_SYSFS > @@ -982,8 +987,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; > + } > + > + arch_make_pages_readonly(folio_page(huge_zero_folio, 0), > + HPAGE_PMD_NR); Can it simply pass the folio? ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/3] mm/huge_memory: make persistent huge zero folio read-only 2026-06-09 19:45 ` Andrew Morton @ 2026-06-10 2:15 ` Lance Yang 2026-06-11 11:28 ` David Hildenbrand (Arm) 0 siblings, 1 reply; 14+ messages in thread From: Lance Yang @ 2026-06-10 2:15 UTC (permalink / raw) To: akpm Cc: xueyuan.chen21, linux-mm, linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, david, ljs, liam, vbabka, rppt, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, lance.yang, yang, jannh, dave.hansen On Tue, Jun 09, 2026 at 12:45:49PM -0700, Andrew Morton wrote: >On Tue, 9 Jun 2026 22:37:59 +0800 Xueyuan Chen <xueyuan.chen21@gmail.com> wrote: > >> The huge zero folio is shared globally, and its contents should never >> change after initialization. As Jann Horn pointed out[1], the kernel has >> had bugs, including security bugs, where read-only pages were later written >> to. If the persistent huge zero folio is read-only in the direct map, such >> writes fault instead of silently corrupting the shared zero contents. >> >> Add arch_make_pages_readonly() so mm code can request read-only direct-map >> protection for a page range. Direct-map protection is >> architecture-specific, so the generic weak implementation does nothing. >> >> This was inspired by Jann Horn's read-only zero page work[1] and follow-up >> discussion[2] 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/CAHbLzkrXXe7r3n3jXgDKtwZhRqj=jDx9E6dLOULohnhBguvi9A@mail.gmail.com/ >> >> ... >> >> --- a/mm/huge_memory.c >> +++ b/mm/huge_memory.c >> @@ -308,6 +308,11 @@ static unsigned long shrink_huge_zero_folio_scan(struct shrinker *shrink, >> return 0; >> } >> >> +bool __weak arch_make_pages_readonly(struct page *page, int nr_pages) >> +{ >> + return false; >> +} >> + >> static struct shrinker *huge_zero_folio_shrinker; >> >> #ifdef CONFIG_SYSFS >> @@ -982,8 +987,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; >> + } >> + >> + arch_make_pages_readonly(folio_page(huge_zero_folio, 0), >> + HPAGE_PMD_NR); > >Can it simply pass the folio? Right, this came from the RFC v1 discussion[1]. David preferred a page- range helper for possible future non-folio callers, not something folio- only. Of course, we could also add a folio wrapper on top of that if needed :) [1] https://lore.kernel.org/linux-mm/929875a2-9e94-4dbc-9c98-b342ccc3f4e2@kernel.org/ Thanks, Lance ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/3] mm/huge_memory: make persistent huge zero folio read-only 2026-06-10 2:15 ` Lance Yang @ 2026-06-11 11:28 ` David Hildenbrand (Arm) 2026-06-11 11:58 ` Lance Yang 0 siblings, 1 reply; 14+ messages in thread From: David Hildenbrand (Arm) @ 2026-06-11 11:28 UTC (permalink / raw) To: Lance Yang, akpm Cc: xueyuan.chen21, linux-mm, linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, ljs, liam, vbabka, rppt, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, yang, jannh, dave.hansen On 6/10/26 04:15, Lance Yang wrote: > > On Tue, Jun 09, 2026 at 12:45:49PM -0700, Andrew Morton wrote: >> On Tue, 9 Jun 2026 22:37:59 +0800 Xueyuan Chen <xueyuan.chen21@gmail.com> wrote: >> >>> The huge zero folio is shared globally, and its contents should never >>> change after initialization. As Jann Horn pointed out[1], the kernel has >>> had bugs, including security bugs, where read-only pages were later written >>> to. If the persistent huge zero folio is read-only in the direct map, such >>> writes fault instead of silently corrupting the shared zero contents. >>> >>> Add arch_make_pages_readonly() so mm code can request read-only direct-map >>> protection for a page range. Direct-map protection is >>> architecture-specific, so the generic weak implementation does nothing. >>> >>> This was inspired by Jann Horn's read-only zero page work[1] and follow-up >>> discussion[2] 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/CAHbLzkrXXe7r3n3jXgDKtwZhRqj=jDx9E6dLOULohnhBguvi9A@mail.gmail.com/ >>> >>> ... >>> >>> --- a/mm/huge_memory.c >>> +++ b/mm/huge_memory.c >>> @@ -308,6 +308,11 @@ static unsigned long shrink_huge_zero_folio_scan(struct shrinker *shrink, >>> return 0; >>> } >>> >>> +bool __weak arch_make_pages_readonly(struct page *page, int nr_pages) >>> +{ >>> + return false; >>> +} >>> + >>> static struct shrinker *huge_zero_folio_shrinker; >>> >>> #ifdef CONFIG_SYSFS >>> @@ -982,8 +987,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; >>> + } >>> + >>> + arch_make_pages_readonly(folio_page(huge_zero_folio, 0), >>> + HPAGE_PMD_NR); >> >> Can it simply pass the folio? > > Right, this came from the RFC v1 discussion[1]. David preferred a page- > range helper for possible future non-folio callers, not something folio- > only. > > Of course, we could also add a folio wrapper on top of that if needed :) Best to document that as part of the patch description: we don't really expect to have a lot of read-only folios in the near future (zero page is rather special; maybe it won't even be a folio in the future). -- Cheers, David ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/3] mm/huge_memory: make persistent huge zero folio read-only 2026-06-11 11:28 ` David Hildenbrand (Arm) @ 2026-06-11 11:58 ` Lance Yang 2026-06-11 12:21 ` David Hildenbrand (Arm) 0 siblings, 1 reply; 14+ messages in thread From: Lance Yang @ 2026-06-11 11:58 UTC (permalink / raw) To: david Cc: lance.yang, akpm, xueyuan.chen21, linux-mm, linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, ljs, liam, vbabka, rppt, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, yang, jannh, dave.hansen On Thu, Jun 11, 2026 at 01:28:58PM +0200, David Hildenbrand (Arm) wrote: >On 6/10/26 04:15, Lance Yang wrote: >> >> On Tue, Jun 09, 2026 at 12:45:49PM -0700, Andrew Morton wrote: >>> On Tue, 9 Jun 2026 22:37:59 +0800 Xueyuan Chen <xueyuan.chen21@gmail.com> wrote: >>> >>>> The huge zero folio is shared globally, and its contents should never >>>> change after initialization. As Jann Horn pointed out[1], the kernel has >>>> had bugs, including security bugs, where read-only pages were later written >>>> to. If the persistent huge zero folio is read-only in the direct map, such >>>> writes fault instead of silently corrupting the shared zero contents. >>>> >>>> Add arch_make_pages_readonly() so mm code can request read-only direct-map >>>> protection for a page range. Direct-map protection is >>>> architecture-specific, so the generic weak implementation does nothing. >>>> >>>> This was inspired by Jann Horn's read-only zero page work[1] and follow-up >>>> discussion[2] 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/CAHbLzkrXXe7r3n3jXgDKtwZhRqj=jDx9E6dLOULohnhBguvi9A@mail.gmail.com/ >>>> >>>> ... >>>> >>>> --- a/mm/huge_memory.c >>>> +++ b/mm/huge_memory.c >>>> @@ -308,6 +308,11 @@ static unsigned long shrink_huge_zero_folio_scan(struct shrinker *shrink, >>>> return 0; >>>> } >>>> >>>> +bool __weak arch_make_pages_readonly(struct page *page, int nr_pages) >>>> +{ >>>> + return false; >>>> +} >>>> + >>>> static struct shrinker *huge_zero_folio_shrinker; >>>> >>>> #ifdef CONFIG_SYSFS >>>> @@ -982,8 +987,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; >>>> + } >>>> + >>>> + arch_make_pages_readonly(folio_page(huge_zero_folio, 0), >>>> + HPAGE_PMD_NR); >>> >>> Can it simply pass the folio? >> >> Right, this came from the RFC v1 discussion[1]. David preferred a page- >> range helper for possible future non-folio callers, not something folio- >> only. >> >> Of course, we could also add a folio wrapper on top of that if needed :) > >Best to document that as part of the patch description: we don't really expect >to have a lot of read-only folios in the near future (zero page is rather >special; maybe it won't even be a folio in the future). Ah, good to know, thanks. Will spell that out in RFC v3. Maybe something like this? The huge zero page is pretty special case, and maybe it won't even be a folio in the future. Since read-only folios are unlikely to become a common thing, a page-range helper is the cleaner fit. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/3] mm/huge_memory: make persistent huge zero folio read-only 2026-06-11 11:58 ` Lance Yang @ 2026-06-11 12:21 ` David Hildenbrand (Arm) 2026-06-11 12:50 ` Lance Yang 0 siblings, 1 reply; 14+ messages in thread From: David Hildenbrand (Arm) @ 2026-06-11 12:21 UTC (permalink / raw) To: Lance Yang Cc: akpm, xueyuan.chen21, linux-mm, linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, ljs, liam, vbabka, rppt, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, yang, jannh, dave.hansen On 6/11/26 13:58, Lance Yang wrote: > > On Thu, Jun 11, 2026 at 01:28:58PM +0200, David Hildenbrand (Arm) wrote: >> On 6/10/26 04:15, Lance Yang wrote: >>> >>> >>> Right, this came from the RFC v1 discussion[1]. David preferred a page- >>> range helper for possible future non-folio callers, not something folio- >>> only. >>> >>> Of course, we could also add a folio wrapper on top of that if needed :) >> >> Best to document that as part of the patch description: we don't really expect >> to have a lot of read-only folios in the near future (zero page is rather >> special; maybe it won't even be a folio in the future). > > Ah, good to know, thanks. Will spell that out in RFC v3. > > Maybe something like this? > > The huge zero page is pretty special case, and maybe it won't even be a > folio in the future. Since read-only folios are unlikely to become a > common thing, a page-range helper is the cleaner fit. Right. And if read-only folios in FSes become a real thing, we can always add infrastructure for that. -- Cheers, David ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH v2 1/3] mm/huge_memory: make persistent huge zero folio read-only 2026-06-11 12:21 ` David Hildenbrand (Arm) @ 2026-06-11 12:50 ` Lance Yang 0 siblings, 0 replies; 14+ messages in thread From: Lance Yang @ 2026-06-11 12:50 UTC (permalink / raw) To: David Hildenbrand (Arm) Cc: akpm, xueyuan.chen21, linux-mm, linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, ljs, liam, vbabka, rppt, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, yang, jannh, dave.hansen On 2026/6/11 20:21, David Hildenbrand (Arm) wrote: > On 6/11/26 13:58, Lance Yang wrote: >> >> On Thu, Jun 11, 2026 at 01:28:58PM +0200, David Hildenbrand (Arm) wrote: >>> On 6/10/26 04:15, Lance Yang wrote: >>>> >>>> >>>> Right, this came from the RFC v1 discussion[1]. David preferred a page- >>>> range helper for possible future non-folio callers, not something folio- >>>> only. >>>> >>>> Of course, we could also add a folio wrapper on top of that if needed :) >>> >>> Best to document that as part of the patch description: we don't really expect >>> to have a lot of read-only folios in the near future (zero page is rather >>> special; maybe it won't even be a folio in the future). >> >> Ah, good to know, thanks. Will spell that out in RFC v3. >> >> Maybe something like this? >> >> The huge zero page is pretty special case, and maybe it won't even be a >> folio in the future. Since read-only folios are unlikely to become a >> common thing, a page-range helper is the cleaner fit. > > Right. And if read-only folios in FSes become a real thing, we can always add > infrastructure for that. Got it, that draws the line nicely :P ^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH v2 2/3] arm64/mm: make pages read-only in the linear map 2026-06-09 14:37 [RFC PATCH v2 0/3] make persistent huge zero folio read-only Xueyuan Chen 2026-06-09 14:37 ` [RFC PATCH v2 1/3] mm/huge_memory: " Xueyuan Chen @ 2026-06-09 14:38 ` Xueyuan Chen 2026-06-09 14:38 ` [RFC PATCH v2 3/3] x86/mm: make pages read-only in the direct map Xueyuan Chen 2 siblings, 0 replies; 14+ messages in thread From: Xueyuan Chen @ 2026-06-09 14:38 UTC (permalink / raw) To: akpm, linux-mm Cc: linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, david, ljs, liam, vbabka, rppt, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, lance.yang, yang, jannh, Xueyuan Chen Implement arch_make_pages_readonly() for arm64. Make the corresponding linear-map range read-only so unexpected writes fault instead of corrupting shared contents. Respect can_set_direct_map() before touching the linear map. If arm64 cannot safely update the linear map at page granularity, leave the mapping unchanged. Co-developed-by: Lance Yang <lance.yang@linux.dev> Signed-off-by: Lance Yang <lance.yang@linux.dev> Signed-off-by: Xueyuan Chen <xueyuan.chen21@gmail.com> --- arch/arm64/mm/pageattr.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c index ce035e1b4eaf..da97ec7d5195 100644 --- a/arch/arm64/mm/pageattr.c +++ b/arch/arm64/mm/pageattr.c @@ -3,6 +3,7 @@ * Copyright (c) 2014, The Linux Foundation. All rights reserved. */ #include <linux/kernel.h> +#include <linux/init.h> #include <linux/mm.h> #include <linux/module.h> #include <linux/mem_encrypt.h> @@ -147,6 +148,18 @@ static int __change_memory_common(unsigned long start, unsigned long size, return ret; } +bool arch_make_pages_readonly(struct page *page, int nr_pages) +{ + unsigned long addr = (unsigned long)page_address(page); + + if (!can_set_direct_map()) + return false; + + return !__change_memory_common(addr, PAGE_SIZE * nr_pages, + __pgprot(PTE_RDONLY), + __pgprot(PTE_WRITE)); +} + static int change_memory_common(unsigned long addr, int numpages, pgprot_t set_mask, pgprot_t clear_mask) { -- 2.47.3 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH v2 3/3] x86/mm: make pages read-only in the direct map 2026-06-09 14:37 [RFC PATCH v2 0/3] make persistent huge zero folio read-only Xueyuan Chen 2026-06-09 14:37 ` [RFC PATCH v2 1/3] mm/huge_memory: " Xueyuan Chen 2026-06-09 14:38 ` [RFC PATCH v2 2/3] arm64/mm: make pages read-only in the linear map Xueyuan Chen @ 2026-06-09 14:38 ` Xueyuan Chen 2 siblings, 0 replies; 14+ messages in thread From: Xueyuan Chen @ 2026-06-09 14:38 UTC (permalink / raw) To: akpm, linux-mm Cc: linux-kernel, linux-arm-kernel, x86, catalin.marinas, will, tglx, mingo, bp, dave.hansen, luto, peterz, hpa, david, ljs, liam, vbabka, rppt, surenb, mhocko, ziy, baolin.wang, npache, ryan.roberts, dev.jain, baohua, lance.yang, yang, jannh, Xueyuan Chen Implement arch_make_pages_readonly() for x86. Make the corresponding direct-map range read-only so unexpected writes fault instead of corrupting shared contents. Reject highmem pages because they have no permanent direct-map address. Treat the set_memory_ro() update as best effort. If it fails, leave the mapping unchanged. Co-developed-by: Lance Yang <lance.yang@linux.dev> Signed-off-by: Lance Yang <lance.yang@linux.dev> Signed-off-by: Xueyuan Chen <xueyuan.chen21@gmail.com> --- arch/x86/mm/init.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index fb67217fddcd..ff0a7003eaeb 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -3,6 +3,7 @@ #include <linux/ioport.h> #include <linux/swap.h> #include <linux/memblock.h> +#include <linux/mm.h> #include <linux/swapfile.h> #include <linux/swapops.h> #include <linux/kmemleak.h> @@ -38,6 +39,14 @@ #include "mm_internal.h" +bool arch_make_pages_readonly(struct page *page, int nr_pages) +{ + if (PageHighMem(page)) + return false; + + return !set_memory_ro((unsigned long)page_address(page), nr_pages); +} + /* * Tables translating between page_cache_type_t and pte encoding. * -- 2.47.3 ^ permalink raw reply related [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-06-11 12:51 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-06-09 14:37 [RFC PATCH v2 0/3] make persistent huge zero folio read-only Xueyuan Chen 2026-06-09 14:37 ` [RFC PATCH v2 1/3] mm/huge_memory: " Xueyuan Chen 2026-06-09 19:33 ` Dave Hansen 2026-06-10 3:20 ` Lance Yang 2026-06-11 6:49 ` Mike Rapoport 2026-06-11 10:35 ` Lance Yang 2026-06-09 19:45 ` Andrew Morton 2026-06-10 2:15 ` Lance Yang 2026-06-11 11:28 ` David Hildenbrand (Arm) 2026-06-11 11:58 ` Lance Yang 2026-06-11 12:21 ` David Hildenbrand (Arm) 2026-06-11 12:50 ` Lance Yang 2026-06-09 14:38 ` [RFC PATCH v2 2/3] arm64/mm: make pages read-only in the linear map Xueyuan Chen 2026-06-09 14:38 ` [RFC PATCH v2 3/3] x86/mm: make pages read-only in the direct map Xueyuan Chen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox