1 From 363cd2b81cfdf706bbfc9ec78db000c9b1ecc552 Mon Sep 17 00:00:00 2001
2 From: Yeoreum Yun <yeoreum.yun@arm.com>
3 Date: Fri, 2 May 2025 19:04:12 +0100
4 Subject: arm64: cpufeature: Move arm64_use_ng_mappings to the .data section to prevent wrong idmap generation
6 From: Yeoreum Yun <yeoreum.yun@arm.com>
8 commit 363cd2b81cfdf706bbfc9ec78db000c9b1ecc552 upstream.
10 The PTE_MAYBE_NG macro sets the nG page table bit according to the value
11 of "arm64_use_ng_mappings". This variable is currently placed in the
12 .bss section. create_init_idmap() is called before the .bss section
13 initialisation which is done in early_map_kernel(). Therefore,
14 data/test_prot in create_init_idmap() could be set incorrectly through
15 the PAGE_KERNEL -> PROT_DEFAULT -> PTE_MAYBE_NG macros.
17 # llvm-objdump-21 --syms vmlinux-gcc | grep arm64_use_ng_mappings
18 ffff800082f242a8 g O .bss 0000000000000001 arm64_use_ng_mappings
20 The create_init_idmap() function disassembly compiled with llvm-21:
22 // create_init_idmap()
23 ffff80008255c058: d10103ff sub sp, sp, #0x40
24 ffff80008255c05c: a9017bfd stp x29, x30, [sp, #0x10]
25 ffff80008255c060: a90257f6 stp x22, x21, [sp, #0x20]
26 ffff80008255c064: a9034ff4 stp x20, x19, [sp, #0x30]
27 ffff80008255c068: 910043fd add x29, sp, #0x10
28 ffff80008255c06c: 90003fc8 adrp x8, 0xffff800082d54000
29 ffff80008255c070: d280e06a mov x10, #0x703 // =1795
30 ffff80008255c074: 91400409 add x9, x0, #0x1, lsl #12 // =0x1000
31 ffff80008255c078: 394a4108 ldrb w8, [x8, #0x290] ------------- (1)
32 ffff80008255c07c: f2e00d0a movk x10, #0x68, lsl #48
33 ffff80008255c080: f90007e9 str x9, [sp, #0x8]
34 ffff80008255c084: aa0103f3 mov x19, x1
35 ffff80008255c088: aa0003f4 mov x20, x0
36 ffff80008255c08c: 14000000 b 0xffff80008255c08c <__pi_create_init_idmap+0x34>
37 ffff80008255c090: aa082d56 orr x22, x10, x8, lsl #11 -------- (2)
39 Note (1) is loading the arm64_use_ng_mappings value in w8 and (2) is set
40 the text or data prot with the w8 value to set PTE_NG bit. If the .bss
41 section isn't initialized, x8 could include a garbage value and generate
44 Annotate arm64_use_ng_mappings as __read_mostly so that it is placed in
47 Fixes: 84b04d3e6bdb ("arm64: kernel: Create initial ID map from C code")
48 Cc: stable@vger.kernel.org # 6.9.x
49 Tested-by: Nathan Chancellor <nathan@kernel.org>
50 Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
51 Link: https://lore.kernel.org/r/20250502180412.3774883-1-yeoreum.yun@arm.com
52 [catalin.marinas@arm.com: use __read_mostly instead of __ro_after_init]
53 [catalin.marinas@arm.com: slight tweaking of the code comment]
54 Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
55 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
57 arch/arm64/kernel/cpufeature.c | 9 ++++++++-
58 1 file changed, 8 insertions(+), 1 deletion(-)
60 --- a/arch/arm64/kernel/cpufeature.c
61 +++ b/arch/arm64/kernel/cpufeature.c
62 @@ -113,7 +113,14 @@ static struct arm64_cpu_capabilities con
64 DECLARE_BITMAP(boot_cpucaps, ARM64_NCAPS);
66 -bool arm64_use_ng_mappings = false;
68 + * arm64_use_ng_mappings must be placed in the .data section, otherwise it
69 + * ends up in the .bss section where it is initialized in early_map_kernel()
70 + * after the MMU (with the idmap) was enabled. create_init_idmap() - which
71 + * runs before early_map_kernel() and reads the variable via PTE_MAYBE_NG -
72 + * may end up generating an incorrect idmap page table attributes.
74 +bool arm64_use_ng_mappings __read_mostly = false;
75 EXPORT_SYMBOL(arm64_use_ng_mappings);
77 DEFINE_PER_CPU_READ_MOSTLY(const char *, this_cpu_vector) = vectors;