]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
arm64: head: avoid over-mapping in map_memory
authorMark Rutland <mark.rutland@arm.com>
Mon, 23 Aug 2021 10:12:53 +0000 (11:12 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 18 Sep 2021 11:41:46 +0000 (13:41 +0200)
commit 90268574a3e8a6b883bd802d702a2738577e1006 upstream.

The `compute_indices` and `populate_entries` macros operate on inclusive
bounds, and thus the `map_memory` macro which uses them also operates
on inclusive bounds.

We pass `_end` and `_idmap_text_end` to `map_memory`, but these are
exclusive bounds, and if one of these is sufficiently aligned (as a
result of kernel configuration, physical placement, and KASLR), then:

* In `compute_indices`, the computed `iend` will be in the page/block *after*
  the final byte of the intended mapping.

* In `populate_entries`, an unnecessary entry will be created at the end
  of each level of table. At the leaf level, this entry will map up to
  SWAPPER_BLOCK_SIZE bytes of physical addresses that we did not intend
  to map.

As we may map up to SWAPPER_BLOCK_SIZE bytes more than intended, we may
violate the boot protocol and map physical address past the 2MiB-aligned
end address we are permitted to map. As we map these with Normal memory
attributes, this may result in further problems depending on what these
physical addresses correspond to.

The final entry at each level may require an additional table at that
level. As EARLY_ENTRIES() calculates an inclusive bound, we allocate
enough memory for this.

Avoid the extraneous mapping by having map_memory convert the exclusive
end address to an inclusive end address by subtracting one, and do
likewise in EARLY_ENTRIES() when calculating the number of required
tables. For clarity, comments are updated to more clearly document which
boundaries the macros operate on.  For consistency with the other
macros, the comments in map_memory are also updated to describe `vstart`
and `vend` as virtual addresses.

Fixes: 0370b31e4845 ("arm64: Extend early page table code to allow for larger kernels")
Cc: <stable@vger.kernel.org> # 4.16.x
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Anshuman Khandual <anshuman.khandual@arm.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Steve Capper <steve.capper@arm.com>
Cc: Will Deacon <will@kernel.org>
Acked-by: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20210823101253.55567-1-mark.rutland@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm64/include/asm/kernel-pgtable.h
arch/arm64/kernel/head.S

index d44df9d62fc9c2f9c1fcc492945c903c6baaeb6a..a54ce2646cba2e94757b3d298fa12e078134fa7f 100644 (file)
@@ -65,8 +65,8 @@
 #define EARLY_KASLR    (0)
 #endif
 
-#define EARLY_ENTRIES(vstart, vend, shift) (((vend) >> (shift)) \
-                                       - ((vstart) >> (shift)) + 1 + EARLY_KASLR)
+#define EARLY_ENTRIES(vstart, vend, shift) \
+       ((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1 + EARLY_KASLR)
 
 #define EARLY_PGDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, PGDIR_SHIFT))
 
index 96873dfa67fd5214dca48d68a98483b6b1bf9d2c..3374bbd18fc66604e4c5aec25c2b76e91ca321ef 100644 (file)
@@ -176,7 +176,7 @@ SYM_CODE_END(preserve_boot_args)
  * to be composed of multiple pages. (This effectively scales the end index).
  *
  *     vstart: virtual address of start of range
- *     vend:   virtual address of end of range
+ *     vend:   virtual address of end of range - we map [vstart, vend]
  *     shift:  shift used to transform virtual address into index
  *     ptrs:   number of entries in page table
  *     istart: index in table corresponding to vstart
@@ -213,17 +213,18 @@ SYM_CODE_END(preserve_boot_args)
  *
  *     tbl:    location of page table
  *     rtbl:   address to be used for first level page table entry (typically tbl + PAGE_SIZE)
- *     vstart: start address to map
- *     vend:   end address to map - we map [vstart, vend]
+ *     vstart: virtual address of start of range
+ *     vend:   virtual address of end of range - we map [vstart, vend - 1]
  *     flags:  flags to use to map last level entries
  *     phys:   physical address corresponding to vstart - physical memory is contiguous
  *     pgds:   the number of pgd entries
  *
  * Temporaries:        istart, iend, tmp, count, sv - these need to be different registers
- * Preserves:  vstart, vend, flags
- * Corrupts:   tbl, rtbl, istart, iend, tmp, count, sv
+ * Preserves:  vstart, flags
+ * Corrupts:   tbl, rtbl, vend, istart, iend, tmp, count, sv
  */
        .macro map_memory, tbl, rtbl, vstart, vend, flags, phys, pgds, istart, iend, tmp, count, sv
+       sub \vend, \vend, #1
        add \rtbl, \tbl, #PAGE_SIZE
        mov \sv, \rtbl
        mov \count, #0