The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* Re: [PATCH v4 02/15] mm: Make empty_zero_page __ro_after_init
       [not found] ` <20260427153416.2103979-19-ardb+git@google.com>
@ 2026-05-08 17:02   ` Jann Horn
  2026-05-11  8:59     ` Ard Biesheuvel
  2026-05-11 18:45     ` Kees Cook
       [not found]   ` <3d1a6b5c-f3bf-462f-879a-cdb5b60868ac@kernel.org>
  2026-05-11  2:55   ` Feng Tang
  2 siblings, 2 replies; 7+ messages in thread
From: Jann Horn @ 2026-05-08 17:02 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-kernel, will, catalin.marinas,
	mark.rutland, Ard Biesheuvel, Ryan Roberts, Anshuman Khandual,
	Liz Prucka, Seth Jenkins, Kees Cook, Mike Rapoport,
	David Hildenbrand, Andrew Morton, linux-mm, linux-hardening

On Mon, Apr 27, 2026 at 5:44 PM Ard Biesheuvel <ardb+git@google.com> wrote:
> The empty zero page is used to back any kernel or user space mapping
> that is supposed to remain cleared, and so the page itself is never
> supposed to be modified.
>
> So make it __ro_after_init rather than __page_aligned_bss: on most
> architectures, this ensures that both the kernel's mapping of it and any
> aliases that are accessible via the kernel direct (linear) map are
> mapped read-only, and cannot be used (inadvertently or maliciously) to
> corrupt the contents of the zero page.
>
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

Reviewed-by: Jann Horn <jannh@google.com>

Sorry, I should have looked at this properly earlier instead of ending
up duplicating this patch with
<https://lore.kernel.org/all/20260508-ro-zeropage-v1-1-9808abc20b49@google.com/>.

> ---
>  mm/mm_init.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/mm/mm_init.c b/mm/mm_init.c
> index f9f8e1af921c..6ca01ed2a5a4 100644
> --- a/mm/mm_init.c
> +++ b/mm/mm_init.c
> @@ -57,7 +57,7 @@ unsigned long zero_page_pfn __ro_after_init;
>  EXPORT_SYMBOL(zero_page_pfn);
>
>  #ifndef __HAVE_COLOR_ZERO_PAGE
> -uint8_t empty_zero_page[PAGE_SIZE] __page_aligned_bss;
> +uint8_t empty_zero_page[PAGE_SIZE] __ro_after_init __aligned(PAGE_SIZE);

I think this is fine as-is; but FWIW:
"__ro_after_init __aligned(PAGE_SIZE)" means that this will land
in the middle of the .data..ro_after_init section, with padding in
front of it to create 4K alignment. So this probably wastes some
RAM on padding.

Looking at "nm ../linux-out/vmlinux | sort" with this patch applied
(from a build without any LTO or such), I see this:
```
[...]
ffffffff8473d378 d shmem_inode_cachep
ffffffff8473d380 d user_buckets
ffffffff8473e000 D zero_page_pfn
ffffffff8473f000 D empty_zero_page
ffffffff84740000 D __zero_page
ffffffff84740008 D pcpu_reserved_chunk
[...]
```
So I think there are almost 4K of padding between zero_page_pfn and
empty_zero_page for alignment; and I think when the linker linked
mm-init.o with the rest of the kernel, it also had to align the
compilation unit's entire .data..ro_after_init section to 4K, which is
why I also got ~3K of padding before zero_page_pfn, resulting in a
total of ~7K of padding.

If you want to change this:
I searched through the arch-specific linker scripts, and I think they
all rely on the generic RO_DATA() macro for emitting the rodata
section; so creating an analogous page-aligned rodata section should
be as simple as adding "*(.rodata..page_aligned)" directly after
"__start_rodata = .;", as I did in my duplicate patch.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 02/15] mm: Make empty_zero_page __ro_after_init
       [not found]   ` <3d1a6b5c-f3bf-462f-879a-cdb5b60868ac@kernel.org>
@ 2026-05-09 11:04     ` Kiryl Shutsemau
  0 siblings, 0 replies; 7+ messages in thread
From: Kiryl Shutsemau @ 2026-05-09 11:04 UTC (permalink / raw)
  To: David Hildenbrand (Arm)
  Cc: Ard Biesheuvel, linux-arm-kernel, linux-kernel, will,
	catalin.marinas, mark.rutland, Ard Biesheuvel, Ryan Roberts,
	Anshuman Khandual, Liz Prucka, Seth Jenkins, Kees Cook,
	Mike Rapoport, Andrew Morton, linux-mm, linux-hardening

On Tue, Apr 28, 2026 at 09:51:09PM +0200, David Hildenbrand (Arm) wrote:
> On 4/27/26 17:34, Ard Biesheuvel wrote:
> > From: Ard Biesheuvel <ardb@kernel.org>
> > 
> > The empty zero page is used to back any kernel or user space mapping
> > that is supposed to remain cleared, and so the page itself is never
> > supposed to be modified.
> > 
> > So make it __ro_after_init rather than __page_aligned_bss: on most
> > architectures, this ensures that both the kernel's mapping of it and any
> > aliases that are accessible via the kernel direct (linear) map are
> > mapped read-only, and cannot be used (inadvertently or maliciously) to
> > corrupt the contents of the zero page.
> > 
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> > ---
> >  mm/mm_init.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/mm/mm_init.c b/mm/mm_init.c
> > index f9f8e1af921c..6ca01ed2a5a4 100644
> > --- a/mm/mm_init.c
> > +++ b/mm/mm_init.c
> > @@ -57,7 +57,7 @@ unsigned long zero_page_pfn __ro_after_init;
> >  EXPORT_SYMBOL(zero_page_pfn);
> >  
> >  #ifndef __HAVE_COLOR_ZERO_PAGE
> > -uint8_t empty_zero_page[PAGE_SIZE] __page_aligned_bss;
> > +uint8_t empty_zero_page[PAGE_SIZE] __ro_after_init __aligned(PAGE_SIZE);
> >  EXPORT_SYMBOL(empty_zero_page);
> >  
> >  struct page *__zero_page __ro_after_init;
> 
> I am no expert on BSS etc, but from what I understand, we'll still get zeroed
> page-aligned memory. I don't know if there is any other impact on not having it
> in bss.page_aligned. I assume no

IIUC, unlike BSS, it will be part of the kernel image. So kernel image
size will grow by PAGE_SIZE. But compressor will eat it as it is all
zeros, so it should be okay.

-- 
  Kiryl Shutsemau / Kirill A. Shutemov

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 02/15] mm: Make empty_zero_page __ro_after_init
       [not found] ` <20260427153416.2103979-19-ardb+git@google.com>
  2026-05-08 17:02   ` [PATCH v4 02/15] mm: Make empty_zero_page __ro_after_init Jann Horn
       [not found]   ` <3d1a6b5c-f3bf-462f-879a-cdb5b60868ac@kernel.org>
@ 2026-05-11  2:55   ` Feng Tang
  2 siblings, 0 replies; 7+ messages in thread
From: Feng Tang @ 2026-05-11  2:55 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: linux-arm-kernel, linux-kernel, will, catalin.marinas,
	mark.rutland, Ard Biesheuvel, Ryan Roberts, Anshuman Khandual,
	Liz Prucka, Seth Jenkins, Kees Cook, Mike Rapoport,
	David Hildenbrand, Andrew Morton, linux-mm, linux-hardening

On Mon, Apr 27, 2026 at 05:34:19PM +0200, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb@kernel.org>
> 
> The empty zero page is used to back any kernel or user space mapping
> that is supposed to remain cleared, and so the page itself is never
> supposed to be modified.
> 
> So make it __ro_after_init rather than __page_aligned_bss: on most
> architectures, this ensures that both the kernel's mapping of it and any
> aliases that are accessible via the kernel direct (linear) map are
> mapped read-only, and cannot be used (inadvertently or maliciously) to
> corrupt the contents of the zero page.

Reviewed-by: Feng Tang <feng.tang@linux.alibaba.com>

We did hit the issue that zero page got corrupted due to non-kernel
reason earlier this year, and it took us weeks to track it down to
zero page corruption and the final root cause, as it randomly happened
to different user space tasks. Thanks for the patch!

> 
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> ---
>  mm/mm_init.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/mm/mm_init.c b/mm/mm_init.c
> index f9f8e1af921c..6ca01ed2a5a4 100644
> --- a/mm/mm_init.c
> +++ b/mm/mm_init.c
> @@ -57,7 +57,7 @@ unsigned long zero_page_pfn __ro_after_init;
>  EXPORT_SYMBOL(zero_page_pfn);
>  
>  #ifndef __HAVE_COLOR_ZERO_PAGE
> -uint8_t empty_zero_page[PAGE_SIZE] __page_aligned_bss;
> +uint8_t empty_zero_page[PAGE_SIZE] __ro_after_init __aligned(PAGE_SIZE);
>  EXPORT_SYMBOL(empty_zero_page);
>  
>  struct page *__zero_page __ro_after_init;
> -- 
> 2.54.0.rc2.544.gc7ae2d5bb8-goog
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 02/15] mm: Make empty_zero_page __ro_after_init
  2026-05-08 17:02   ` [PATCH v4 02/15] mm: Make empty_zero_page __ro_after_init Jann Horn
@ 2026-05-11  8:59     ` Ard Biesheuvel
  2026-05-11 14:40       ` Jann Horn
  2026-05-11 18:45     ` Kees Cook
  1 sibling, 1 reply; 7+ messages in thread
From: Ard Biesheuvel @ 2026-05-11  8:59 UTC (permalink / raw)
  To: Jann Horn, Ard Biesheuvel
  Cc: linux-arm-kernel, linux-kernel, Will Deacon, Catalin Marinas,
	Mark Rutland, Ryan Roberts, Anshuman Khandual, Liz Prucka,
	Seth Jenkins, Kees Cook, Mike Rapoport, David Hildenbrand,
	Andrew Morton, linux-mm, linux-hardening


On Fri, 8 May 2026, at 19:02, Jann Horn wrote:
> On Mon, Apr 27, 2026 at 5:44 PM Ard Biesheuvel <ardb+git@google.com> wrote:
>> The empty zero page is used to back any kernel or user space mapping
>> that is supposed to remain cleared, and so the page itself is never
>> supposed to be modified.
>>
>> So make it __ro_after_init rather than __page_aligned_bss: on most
>> architectures, this ensures that both the kernel's mapping of it and any
>> aliases that are accessible via the kernel direct (linear) map are
>> mapped read-only, and cannot be used (inadvertently or maliciously) to
>> corrupt the contents of the zero page.
>>
>> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
>
> Reviewed-by: Jann Horn <jannh@google.com>
>

Thanks

> Sorry, I should have looked at this properly earlier instead of ending
> up duplicating this patch with
> <https://lore.kernel.org/all/20260508-ro-zeropage-v1-1-9808abc20b49@google.com/>.
>

No worries. I might borrow some of that rationale btw

>> ---
>>  mm/mm_init.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/mm/mm_init.c b/mm/mm_init.c
>> index f9f8e1af921c..6ca01ed2a5a4 100644
>> --- a/mm/mm_init.c
>> +++ b/mm/mm_init.c
>> @@ -57,7 +57,7 @@ unsigned long zero_page_pfn __ro_after_init;
>>  EXPORT_SYMBOL(zero_page_pfn);
>>
>>  #ifndef __HAVE_COLOR_ZERO_PAGE
>> -uint8_t empty_zero_page[PAGE_SIZE] __page_aligned_bss;
>> +uint8_t empty_zero_page[PAGE_SIZE] __ro_after_init __aligned(PAGE_SIZE);
>
> I think this is fine as-is; but FWIW:
> "__ro_after_init __aligned(PAGE_SIZE)" means that this will land
> in the middle of the .data..ro_after_init section, with padding in
> front of it to create 4K alignment. So this probably wastes some
> RAM on padding.
>
> Looking at "nm ../linux-out/vmlinux | sort" with this patch applied
> (from a build without any LTO or such), I see this:
> ```
> [...]
> ffffffff8473d378 d shmem_inode_cachep
> ffffffff8473d380 d user_buckets
> ffffffff8473e000 D zero_page_pfn
> ffffffff8473f000 D empty_zero_page
> ffffffff84740000 D __zero_page
> ffffffff84740008 D pcpu_reserved_chunk
> [...]
> ```
> So I think there are almost 4K of padding between zero_page_pfn and
> empty_zero_page for alignment; and I think when the linker linked
> mm-init.o with the rest of the kernel, it also had to align the
> compilation unit's entire .data..ro_after_init section to 4K, which is
> why I also got ~3K of padding before zero_page_pfn, resulting in a
> total of ~7K of padding.
>
> If you want to change this:
> I searched through the arch-specific linker scripts, and I think they
> all rely on the generic RO_DATA() macro for emitting the rodata
> section; so creating an analogous page-aligned rodata section should
> be as simple as adding "*(.rodata..page_aligned)" directly after
> "__start_rodata = .;", as I did in my duplicate patch.

I think we should simply do something along the lines of the below,
considering that the size of a data object tends to correlate with
its minimum alignment.

I do find it rather puzzling that the compiler emits empty_zero_page
*after* zero_page_pfn - ideally, we'd combine the below with
-fdata-sections so that the linker sees all individual objects, but
I suspect that would create some problems elsewhere.


--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -452,7 +452,7 @@
 #define RO_AFTER_INIT_DATA                                   \
        . = ALIGN(8);                                         \
        __start_ro_after_init = .;                            \
-       *(.data..ro_after_init)                               \
+       *(SORT_BY_ALIGNMENT(.data..ro_after_init))            \
        JUMP_TABLE_DATA                                       \
        STATIC_CALL_DATA                                      \
        __end_ro_after_init = .;



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 02/15] mm: Make empty_zero_page __ro_after_init
  2026-05-11  8:59     ` Ard Biesheuvel
@ 2026-05-11 14:40       ` Jann Horn
  0 siblings, 0 replies; 7+ messages in thread
From: Jann Horn @ 2026-05-11 14:40 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Ard Biesheuvel, linux-arm-kernel, linux-kernel, Will Deacon,
	Catalin Marinas, Mark Rutland, Ryan Roberts, Anshuman Khandual,
	Liz Prucka, Seth Jenkins, Kees Cook, Mike Rapoport,
	David Hildenbrand, Andrew Morton, linux-mm, linux-hardening

On Mon, May 11, 2026 at 10:59 AM Ard Biesheuvel <ardb@kernel.org> wrote:
> I think we should simply do something along the lines of the below,
> considering that the size of a data object tends to correlate with
> its minimum alignment.
>
> I do find it rather puzzling that the compiler emits empty_zero_page
> *after* zero_page_pfn - ideally, we'd combine the below with
> -fdata-sections so that the linker sees all individual objects, but
> I suspect that would create some problems elsewhere.
>
>
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -452,7 +452,7 @@
>  #define RO_AFTER_INIT_DATA                                   \
>         . = ALIGN(8);                                         \
>         __start_ro_after_init = .;                            \
> -       *(.data..ro_after_init)                               \
> +       *(SORT_BY_ALIGNMENT(.data..ro_after_init))            \

Oh, neat, I didn't realize that's possible. That seems like a nicer
approach... (Assuming that it doesn't cause cache efficiency issues
somehow, I imagine it could be possible that source-code-adjacent
objects should also be located next to each other for cache/TLB
efficiency... but I have no concrete reason to think that, just a
thought.)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 02/15] mm: Make empty_zero_page __ro_after_init
  2026-05-08 17:02   ` [PATCH v4 02/15] mm: Make empty_zero_page __ro_after_init Jann Horn
  2026-05-11  8:59     ` Ard Biesheuvel
@ 2026-05-11 18:45     ` Kees Cook
  2026-05-11 19:01       ` Jann Horn
  1 sibling, 1 reply; 7+ messages in thread
From: Kees Cook @ 2026-05-11 18:45 UTC (permalink / raw)
  To: Jann Horn
  Cc: Ard Biesheuvel, linux-arm-kernel, linux-kernel, will,
	catalin.marinas, mark.rutland, Ard Biesheuvel, Ryan Roberts,
	Anshuman Khandual, Liz Prucka, Seth Jenkins, Mike Rapoport,
	David Hildenbrand, Andrew Morton, linux-mm, linux-hardening

On Fri, May 08, 2026 at 07:02:51PM +0200, Jann Horn wrote:
> On Mon, Apr 27, 2026 at 5:44 PM Ard Biesheuvel <ardb+git@google.com> wrote:
> > The empty zero page is used to back any kernel or user space mapping
> > that is supposed to remain cleared, and so the page itself is never
> > supposed to be modified.
> >
> > So make it __ro_after_init rather than __page_aligned_bss: on most
> > architectures, this ensures that both the kernel's mapping of it and any
> > aliases that are accessible via the kernel direct (linear) map are
> > mapped read-only, and cannot be used (inadvertently or maliciously) to
> > corrupt the contents of the zero page.
> >
> > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> 
> Reviewed-by: Jann Horn <jannh@google.com>
> 
> Sorry, I should have looked at this properly earlier instead of ending
> up duplicating this patch with
> <https://lore.kernel.org/all/20260508-ro-zeropage-v1-1-9808abc20b49@google.com/>.

As you mention in your testing of the patch, could we add an LKDTM test
that does the same to catch any regressions?

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v4 02/15] mm: Make empty_zero_page __ro_after_init
  2026-05-11 18:45     ` Kees Cook
@ 2026-05-11 19:01       ` Jann Horn
  0 siblings, 0 replies; 7+ messages in thread
From: Jann Horn @ 2026-05-11 19:01 UTC (permalink / raw)
  To: Kees Cook
  Cc: Ard Biesheuvel, linux-arm-kernel, linux-kernel, will,
	catalin.marinas, mark.rutland, Ard Biesheuvel, Ryan Roberts,
	Anshuman Khandual, Liz Prucka, Seth Jenkins, Mike Rapoport,
	David Hildenbrand, Andrew Morton, linux-mm, linux-hardening

On Mon, May 11, 2026 at 8:45 PM Kees Cook <kees@kernel.org> wrote:
> On Fri, May 08, 2026 at 07:02:51PM +0200, Jann Horn wrote:
> > On Mon, Apr 27, 2026 at 5:44 PM Ard Biesheuvel <ardb+git@google.com> wrote:
> > > The empty zero page is used to back any kernel or user space mapping
> > > that is supposed to remain cleared, and so the page itself is never
> > > supposed to be modified.
> > >
> > > So make it __ro_after_init rather than __page_aligned_bss: on most
> > > architectures, this ensures that both the kernel's mapping of it and any
> > > aliases that are accessible via the kernel direct (linear) map are
> > > mapped read-only, and cannot be used (inadvertently or maliciously) to
> > > corrupt the contents of the zero page.
> > >
> > > Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> >
> > Reviewed-by: Jann Horn <jannh@google.com>
> >
> > Sorry, I should have looked at this properly earlier instead of ending
> > up duplicating this patch with
> > <https://lore.kernel.org/all/20260508-ro-zeropage-v1-1-9808abc20b49@google.com/>.
>
> As you mention in your testing of the patch, could we add an LKDTM test
> that does the same to catch any regressions?

Shouldn't be too hard - LKDTM crashtypes don't accept arguments, so we
couldn't easily pass in a userspace pointer, I think, but we could
make a crashtype that allocates anon memory with do_mmap() (under
mmap_lock), then GUP on the allocated userspace address, then writes
into the obtained address with something like atomic_add(0, <pointer
from kmap(page)>) to trigger a write access without actually changing
memory contents...

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-05-11 19:01 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20260427153416.2103979-17-ardb+git@google.com>
     [not found] ` <20260427153416.2103979-19-ardb+git@google.com>
2026-05-08 17:02   ` [PATCH v4 02/15] mm: Make empty_zero_page __ro_after_init Jann Horn
2026-05-11  8:59     ` Ard Biesheuvel
2026-05-11 14:40       ` Jann Horn
2026-05-11 18:45     ` Kees Cook
2026-05-11 19:01       ` Jann Horn
     [not found]   ` <3d1a6b5c-f3bf-462f-879a-cdb5b60868ac@kernel.org>
2026-05-09 11:04     ` Kiryl Shutsemau
2026-05-11  2:55   ` Feng Tang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox