linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Ard Biesheuvel <ardb@kernel.org>
To: linux-arm-kernel@lists.infradead.org
Cc: Ard Biesheuvel <ardb@kernel.org>, Marc Zyngier <maz@kernel.org>,
	Will Deacon <will@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Kees Cook <keescook@chromium.org>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Mark Brown <broonie@kernel.org>,
	Anshuman Khandual <anshuman.khandual@arm.com>,
	Richard Henderson <richard.henderson@linaro.org>,
	Ryan Roberts <ryan.roberts@arm.com>
Subject: [PATCH v2 04/19] arm64: kaslr: Adjust randomization range dynamically
Date: Thu, 24 Nov 2022 13:39:17 +0100	[thread overview]
Message-ID: <20221124123932.2648991-5-ardb@kernel.org> (raw)
In-Reply-To: <20221124123932.2648991-1-ardb@kernel.org>

Currently, we base the KASLR randomization range on a rough estimate of
the available space in the vmalloc region: the lower 1/4th has the module
region and the upper 1/4th has the fixmap, vmemmap and PCI I/O ranges,
and so we pick a random location in the remaining space in the middle.

Once we enable support for 5-level paging with 4k pages, this no longer
works: the vmemmap region, being dimensioned to cover a 52-bit linear
region, takes up so much space in the upper VA region (whose size is based
on a 48-bit VA space for compatibility with non-LVA hardware) that the
region above the vmalloc region takes up more than a quarter of the
available space.

So instead of a heuristic, let's derive the randomization range from the
actual boundaries of the various regions. Note that this requires some
tweaks to the early fixmap init logic so it can deal with upper
translation levels having already been populated by the time we reach
that function. Note, however, that the level 3 page table cannot be
shared between the fixmap and the kernel, so this needs to be taken into
account when defining the range.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm64/kernel/pi/kaslr_early.c | 23 +++++++++++++++-----
 arch/arm64/mm/mmu.c                | 21 +++++-------------
 2 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/arch/arm64/kernel/pi/kaslr_early.c b/arch/arm64/kernel/pi/kaslr_early.c
index 965515f7f180..51142c4f2659 100644
--- a/arch/arm64/kernel/pi/kaslr_early.c
+++ b/arch/arm64/kernel/pi/kaslr_early.c
@@ -13,7 +13,9 @@
 #include <linux/string.h>
 
 #include <asm/archrandom.h>
+#include <asm/boot.h>
 #include <asm/memory.h>
+#include <asm/pgtable.h>
 
 #include "pi.h"
 
@@ -40,6 +42,16 @@ static u64 __init get_kaslr_seed(void *fdt, int node)
 
 u64 __init kaslr_early_init(void *fdt, int chosen)
 {
+	/*
+	 * The kernel can be mapped almost anywhere in the vmalloc region,
+	 * although we have to ensure that we don't share a level 3 table with
+	 * the fixmap, which installs its own statically allocated one (bm_pte)
+	 * and manipulates the slots by writing into the array directly.
+	 * We also have to account for the offset modulo 2 MiB resulting from
+	 * the physical placement of the image.
+	 */
+	const u64 range = (VMALLOC_END & PMD_MASK) - MODULES_END -
+			  ((u64)_end - ALIGN_DOWN((u64)_text, MIN_KIMG_ALIGN));
 	u64 seed;
 
 	if (cpuid_feature_extract_unsigned_field(arm64_sw_feature_override.val,
@@ -56,11 +68,10 @@ u64 __init kaslr_early_init(void *fdt, int chosen)
 	memstart_offset_seed = seed & U16_MAX;
 
 	/*
-	 * OK, so we are proceeding with KASLR enabled. Calculate a suitable
-	 * kernel image offset from the seed. Let's place the kernel in the
-	 * middle half of the VMALLOC area (VA_BITS_MIN - 2), and stay clear of
-	 * the lower and upper quarters to avoid colliding with other
-	 * allocations.
+	 * Multiply 'range' by a value in [0 .. U32_MAX], and shift the result
+	 * right by 32 bits, to obtain a value in the range [0 .. range). To
+	 * avoid loss of precision in the multiplication, split the right shift
+	 * in two shifts by 16 (range is 64k aligned in any case)
 	 */
-	return BIT(VA_BITS_MIN - 3) + (seed & GENMASK(VA_BITS_MIN - 3, 16));
+	return (((range >> 16) * (seed >> 32)) >> 16) & ~(MIN_KIMG_ALIGN - 1);
 }
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 6942255056ae..222c1154b550 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1222,23 +1222,14 @@ void __init early_fixmap_init(void)
 	pgdp = pgd_offset_k(addr);
 	p4dp = p4d_offset(pgdp, addr);
 	p4d = READ_ONCE(*p4dp);
-	if (CONFIG_PGTABLE_LEVELS > 3 &&
-	    !(p4d_none(p4d) || p4d_page_paddr(p4d) == __pa_symbol(bm_pud))) {
-		/*
-		 * We only end up here if the kernel mapping and the fixmap
-		 * share the top level pgd entry, which should only happen on
-		 * 16k/4 levels configurations.
-		 */
-		BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
-		pudp = pud_offset_kimg(p4dp, addr);
-	} else {
-		if (p4d_none(p4d))
-			__p4d_populate(p4dp, __pa_symbol(bm_pud), P4D_TYPE_TABLE);
-		pudp = fixmap_pud(addr);
-	}
+	if (p4d_none(p4d))
+		__p4d_populate(p4dp, __pa_symbol(bm_pud), P4D_TYPE_TABLE);
+
+	pudp = pud_offset_kimg(p4dp, addr);
 	if (pud_none(READ_ONCE(*pudp)))
 		__pud_populate(pudp, __pa_symbol(bm_pmd), PUD_TYPE_TABLE);
-	pmdp = fixmap_pmd(addr);
+
+	pmdp = pmd_offset_kimg(pudp, addr);
 	__pmd_populate(pmdp, __pa_symbol(bm_pte), PMD_TYPE_TABLE);
 
 	/*
-- 
2.38.1.584.g0f3c55d4c2-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2022-11-24 12:42 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-24 12:39 [PATCH v2 00/19] arm64: Enable LPA2 support for 4k and 16k pages Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 01/19] arm64/mm: Simplify and document pte_to_phys() for 52 bit addresses Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 02/19] arm64/mm: Add FEAT_LPA2 specific TCR_EL1.DS field Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 03/19] arm64/mm: Add FEAT_LPA2 specific ID_AA64MMFR0.TGRAN[2] Ard Biesheuvel
2022-11-24 12:39 ` Ard Biesheuvel [this message]
2022-11-24 12:39 ` [PATCH v2 05/19] arm64: mm: get rid of kimage_vaddr global variable Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 06/19] arm64: head: remove order argument from early mapping routine Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 07/19] arm64: mm: Handle LVA support as a CPU feature Ard Biesheuvel
2022-11-28 14:54   ` Ryan Roberts
2022-11-24 12:39 ` [PATCH v2 08/19] arm64: mm: Deal with potential ID map extension if VA_BITS > VA_BITS_MIN Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 09/19] arm64: mm: Add feature override support for LVA Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 10/19] arm64: mm: Wire up TCR.DS bit to PTE shareability fields Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 11/19] arm64: mm: Add LPA2 support to phys<->pte conversion routines Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 12/19] arm64: mm: Add definitions to support 5 levels of paging Ard Biesheuvel
2022-11-28 16:17   ` Ryan Roberts
2022-11-28 16:22     ` Ard Biesheuvel
2022-11-28 18:00       ` Marc Zyngier
2022-11-28 18:20         ` Ryan Roberts
2022-11-29 15:46       ` Ryan Roberts
2022-11-29 15:48         ` Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 13/19] arm64: mm: add 5 level paging support to G-to-nG conversion routine Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 14/19] arm64: Enable LPA2 at boot if supported by the system Ard Biesheuvel
2022-11-28 14:54   ` Ryan Roberts
2022-11-24 12:39 ` [PATCH v2 15/19] arm64: mm: Add 5 level paging support to fixmap and swapper handling Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 16/19] arm64: kasan: Reduce minimum shadow alignment and enable 5 level paging Ard Biesheuvel
2022-11-24 17:44   ` Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 17/19] arm64: mm: Add support for folding PUDs at runtime Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 18/19] arm64: ptdump: Disregard unaddressable VA space Ard Biesheuvel
2022-11-24 12:39 ` [PATCH v2 19/19] arm64: Enable 52-bit virtual addressing for 4k and 16k granule configs Ard Biesheuvel
2022-11-24 14:39 ` [PATCH v2 00/19] arm64: Enable LPA2 support for 4k and 16k pages Ryan Roberts
2022-11-24 17:14   ` Ard Biesheuvel
2022-11-25  9:22     ` Ryan Roberts
2022-11-25  9:35       ` Ard Biesheuvel
2022-11-25 10:07         ` Ryan Roberts
2022-11-25 10:36           ` Ard Biesheuvel
2022-11-25 14:12             ` Ryan Roberts
2022-11-25 14:19               ` Ard Biesheuvel
2022-11-29 15:31 ` Ryan Roberts
2022-11-29 15:47   ` Ard Biesheuvel
2022-11-29 16:35     ` Ryan Roberts
2022-11-29 16:56       ` Ard Biesheuvel
2022-12-01 12:22         ` Ryan Roberts
2022-12-01 13:43           ` Ard Biesheuvel
2022-12-01 16:00             ` Ryan Roberts

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221124123932.2648991-5-ardb@kernel.org \
    --to=ardb@kernel.org \
    --cc=anshuman.khandual@arm.com \
    --cc=broonie@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=keescook@chromium.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=mark.rutland@arm.com \
    --cc=maz@kernel.org \
    --cc=richard.henderson@linaro.org \
    --cc=ryan.roberts@arm.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).