diff mbox series

[1/6] powerpc/mm/radix: Fix off-by-one in split mapping logic

Message ID 20181019041334.4945-1-mpe@ellerman.id.au (mailing list archive)
State Accepted
Commit 5c6499b7041b43807dfaeda28aa87fc0e62558f7
Headers show
Series [1/6] powerpc/mm/radix: Fix off-by-one in split mapping logic | expand

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success next/apply_patch Successfully applied
snowpatch_ozlabs/checkpatch warning Test checkpatch on branch next

Commit Message

Michael Ellerman Oct. 19, 2018, 4:13 a.m. UTC
When we have CONFIG_STRICT_KERNEL_RWX enabled, we try to split the
kernel linear (1:1) mapping so that the kernel text is in a separate
page to kernel data, so we can mark the former read-only.

We could achieve that just by always using 64K pages for the linear
mapping, but we try to be smarter. Instead we use huge pages when
possible, and only switch to smaller pages when necessary.

However we have an off-by-one bug in that logic, which causes us to
calculate the wrong boundary between text and data.

For example with the end of the kernel text at 16M we see:

  radix-mmu: Mapped 0x0000000000000000-0x0000000001200000 with 64.0 KiB pages
  radix-mmu: Mapped 0x0000000001200000-0x0000000040000000 with 2.00 MiB pages
  radix-mmu: Mapped 0x0000000040000000-0x0000000100000000 with 1.00 GiB pages

ie. we mapped from 0 to 18M with 64K pages, even though the boundary
between text and data is at 16M.

With the fix we see we're correctly hitting the 16M boundary:

  radix-mmu: Mapped 0x0000000000000000-0x0000000001000000 with 64.0 KiB pages
  radix-mmu: Mapped 0x0000000001000000-0x0000000040000000 with 2.00 MiB pages
  radix-mmu: Mapped 0x0000000040000000-0x0000000100000000 with 1.00 GiB pages

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/mm/pgtable-radix.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Comments

Michael Ellerman Oct. 22, 2018, 9:39 a.m. UTC | #1
On Fri, 2018-10-19 at 04:13:29 UTC, Michael Ellerman wrote:
> When we have CONFIG_STRICT_KERNEL_RWX enabled, we try to split the
> kernel linear (1:1) mapping so that the kernel text is in a separate
> page to kernel data, so we can mark the former read-only.
> 
> We could achieve that just by always using 64K pages for the linear
> mapping, but we try to be smarter. Instead we use huge pages when
> possible, and only switch to smaller pages when necessary.
> 
> However we have an off-by-one bug in that logic, which causes us to
> calculate the wrong boundary between text and data.
> 
> For example with the end of the kernel text at 16M we see:
> 
>   radix-mmu: Mapped 0x0000000000000000-0x0000000001200000 with 64.0 KiB pages
>   radix-mmu: Mapped 0x0000000001200000-0x0000000040000000 with 2.00 MiB pages
>   radix-mmu: Mapped 0x0000000040000000-0x0000000100000000 with 1.00 GiB pages
> 
> ie. we mapped from 0 to 18M with 64K pages, even though the boundary
> between text and data is at 16M.
> 
> With the fix we see we're correctly hitting the 16M boundary:
> 
>   radix-mmu: Mapped 0x0000000000000000-0x0000000001000000 with 64.0 KiB pages
>   radix-mmu: Mapped 0x0000000001000000-0x0000000040000000 with 2.00 MiB pages
>   radix-mmu: Mapped 0x0000000040000000-0x0000000100000000 with 1.00 GiB pages
> 
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>

Series applied to powerpc next.

https://git.kernel.org/powerpc/c/5c6499b7041b43807dfaeda28aa87f

cheers
diff mbox series

Patch

diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c
index c879979faa73..d88d76231754 100644
--- a/arch/powerpc/mm/pgtable-radix.c
+++ b/arch/powerpc/mm/pgtable-radix.c
@@ -294,14 +294,14 @@  static int __meminit create_physical_mapping(unsigned long start,
 		}
 
 		if (split_text_mapping && (mapping_size == PUD_SIZE) &&
-			(addr <= __pa_symbol(__init_begin)) &&
+			(addr < __pa_symbol(__init_begin)) &&
 			(addr + mapping_size) >= __pa_symbol(_stext)) {
 			max_mapping_size = PMD_SIZE;
 			goto retry;
 		}
 
 		if (split_text_mapping && (mapping_size == PMD_SIZE) &&
-		    (addr <= __pa_symbol(__init_begin)) &&
+		    (addr < __pa_symbol(__init_begin)) &&
 		    (addr + mapping_size) >= __pa_symbol(_stext)) {
 			mapping_size = PAGE_SIZE;
 			psize = mmu_virtual_psize;