create_init_idmap() could be called before .bss section initialization which is done in early_map_kernel(). Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro.
PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". and this variable places in .bss section.
# llvm-objdump-21 --syms vmlinux-gcc | grep arm64_use_ng_mappings ffff800082f242a8 g O .bss 0000000000000001 arm64_use_ng_mappings
If .bss section doesn't initialized, "arm64_use_ng_mappings" would be set with garbage value and then the text_prot or data_prot could be set incorrectly.
Here is what i saw with kernel compiled via llvm-21
// create_init_idmap() ffff80008255c058: d10103ff sub sp, sp, #0x40 ffff80008255c05c: a9017bfd stp x29, x30, [sp, #0x10] ffff80008255c060: a90257f6 stp x22, x21, [sp, #0x20] ffff80008255c064: a9034ff4 stp x20, x19, [sp, #0x30] ffff80008255c068: 910043fd add x29, sp, #0x10 ffff80008255c06c: 90003fc8 adrp x8, 0xffff800082d54000 ffff80008255c070: d280e06a mov x10, #0x703 // =1795 ffff80008255c074: 91400409 add x9, x0, #0x1, lsl #12 // =0x1000 ffff80008255c078: 394a4108 ldrb w8, [x8, #0x290] ------------- (1) ffff80008255c07c: f2e00d0a movk x10, #0x68, lsl #48 ffff80008255c080: f90007e9 str x9, [sp, #0x8] ffff80008255c084: aa0103f3 mov x19, x1 ffff80008255c088: aa0003f4 mov x20, x0 ffff80008255c08c: 14000000 b 0xffff80008255c08c <__pi_create_init_idmap+0x34> ffff80008255c090: aa082d56 orr x22, x10, x8, lsl #11 -------- (2)
Note, (1) is load the arm64_use_ng_mappings value in w8 and (2) is set the text or data prot with the w8 value to set PTE_NG bit. If .bss section doesn't initialized, x8 can include garbage value -- In case of some platform, x8 loaded with 0xcf -- it could generate wrong mapping. (i.e) text_prot is expected with PAGE_KERNEL_ROX(0x0040000000000F83) but with garbage x8 -- 0xcf, it sets with (0x0040000000067F83) and This makes boot failure with translation fault.
This error cannot happen according to code generated by compiler.
here is the case of gcc: ffff80008260a940 <__pi_create_init_idmap>: ffff80008260a940: d100c3ff sub sp, sp, #0x30 ffff80008260a944: aa0003ed mov x13, x0 ffff80008260a948: 91400400 add x0, x0, #0x1, lsl #12 // =0x1000 ffff80008260a94c: a9017bfd stp x29, x30, [sp, #0x10] ffff80008260a950: 910043fd add x29, sp, #0x10 ffff80008260a954: f90017e0 str x0, [sp, #0x28] ffff80008260a958: d00048c0 adrp x0, 0xffff800082f24000 <reset_devices> ffff80008260a95c: 394aa000 ldrb w0, [x0, #0x2a8] ffff80008260a960: 37000640 tbnz w0, #0x0, 0xffff80008260aa28 <__pi_create_init_idmap+0xe8> ---(3) ffff80008260a964: d280f060 mov x0, #0x783 // =1923 ffff80008260a968: d280e062 mov x2, #0x703 // =1795 ffff80008260a96c: f2e00800 movk x0, #0x40, lsl #48 ffff80008260a970: f2e00d02 movk x2, #0x68, lsl #48 ffff80008260a974: aa2103e4 mvn x4, x1 ffff80008260a978: 8a210049 bic x9, x2, x1 ... ffff80008260aa28: d281f060 mov x0, #0xf83 // =3971 ffff80008260aa2c: d281e062 mov x2, #0xf03 // =3843 ffff80008260aa30: f2e00800 movk x0, #0x40, lsl #48
In case of gcc, according to value of arm64_use_ng_mappings (annoated as(3)), it branches to each prot settup code. However this is also problem since it branches according to garbage value too -- idmapping with incorrect pgprot.
To resolve this, annotate arm64_use_ng_mappings as ro_after_init.
Fixes: 84b04d3e6bdb ("arm64: kernel: Create initial ID map from C code") Cc: stable@vger.kernel.org # 6.9.x Tested-by: Nathan Chancellor nathan@kernel.org Signed-off-by: Yeoreum Yun yeoreum.yun@arm.com --- Since v1: - add comments explaining arm64_use_ng_mappings shouldn't place .bss section - fix type on commit message - https://lore.kernel.org/all/20250502145755.3751405-1-yeoreum.yun@arm.com/
There is another way to solve this problem by setting test/data_prot with _PAGE_DEFAULT which doesn't include PTE_MAYBE_NG with constanst check in create_init_idmap() to be free from arm64_use_ng_mappings. but i think it would be better to change arm64_use_ng_mappings as ro_after_init because it doesn't change after init phase and solve this problem too. --- arch/arm64/kernel/cpufeature.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index d2104a1e7843..913ae2cead98 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -114,7 +114,18 @@ static struct arm64_cpu_capabilities const __ro_after_init *cpucap_ptrs[ARM64_NC
DECLARE_BITMAP(boot_cpucaps, ARM64_NCAPS);
-bool arm64_use_ng_mappings = false; +/* + * The variable arm64_use_ng_mappings should be placed in the .rodata section. + * Otherwise, it would end up in the .bss section, where it is initialized in + * early_map_kernel(). This can cause problems because the PTE_MAYBE_NG macro + * uses this variable, and create_init_idmap() — which might run before + * early_map_kernel() — could end up generating an incorrect idmap table. + * + * In other words, accessing variable placed in .bss section before + * early_map_kernel() will return garbage, + * potentially resulting in a wrong pgprot value. + */ +bool arm64_use_ng_mappings __ro_after_init = false; EXPORT_SYMBOL(arm64_use_ng_mappings);
DEFINE_PER_CPU_READ_MOSTLY(const char *, this_cpu_vector) = vectors; -- LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote:
create_init_idmap() could be called before .bss section initialization which is done in early_map_kernel(). Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro.
PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". and this variable places in .bss section.
[...]
Applied to arm64 (for-next/fixes), with some slight tweaking of the comment, thanks!
[1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation https://git.kernel.org/arm64/c/12657bcd1835
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote:
On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote:
create_init_idmap() could be called before .bss section initialization which is done in early_map_kernel(). Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro.
PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". and this variable places in .bss section.
[...]
Applied to arm64 (for-next/fixes), with some slight tweaking of the comment, thanks!
[1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
$ clang --version Debian clang version 19.1.5 (1) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
I didn't have time to investigate, disassemble etc. I'll have a look next week.
Hi Catalin,
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote:
On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote:
create_init_idmap() could be called before .bss section initialization which is done in early_map_kernel(). Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro.
PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". and this variable places in .bss section.
[...]
Applied to arm64 (for-next/fixes), with some slight tweaking of the comment, thanks!
[1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
$ clang --version Debian clang version 19.1.5 (1) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
I didn't have time to investigate, disassemble etc. I'll have a look next week.
Just for your information. When I see the debian package, clang 19.1.5-1 doesn't supply anymore: - https://ftp.debian.org/debian/pool/main/l/llvm-toolchain-19/
and the default version for sid is below:
$ clang-19 --version Debian clang version 19.1.7 (3) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
When I tested with above version with arm64-linux's for-next/fixes including this patch. it works well.
Thanks
-- Sincerely, Yeoreum Yun
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote:
On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote:
create_init_idmap() could be called before .bss section initialization which is done in early_map_kernel(). Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro.
PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". and this variable places in .bss section.
[...]
Applied to arm64 (for-next/fixes), with some slight tweaking of the comment, thanks!
[1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
$ clang --version Debian clang version 19.1.5 (1) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
I didn't have time to investigate, disassemble etc. I'll have a look next week.
Just for your information. When I see the debian package, clang 19.1.5-1 doesn't supply anymore:
and the default version for sid is below:
$ clang-19 --version Debian clang version 19.1.7 (3) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
When I tested with above version with arm64-linux's for-next/fixes including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
I haven't debugged it yet but I wonder whether something wants to write this variable after it was made read-only (well, I couldn't find any by grep'ing the code, so it needs some step-by-step debugging).
Hi Catalin,
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote:
On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote:
create_init_idmap() could be called before .bss section initialization which is done in early_map_kernel(). Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro.
PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". and this variable places in .bss section.
[...]
Applied to arm64 (for-next/fixes), with some slight tweaking of the comment, thanks!
[1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
$ clang --version Debian clang version 19.1.5 (1) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
I didn't have time to investigate, disassemble etc. I'll have a look next week.
Just for your information. When I see the debian package, clang 19.1.5-1 doesn't supply anymore:
and the default version for sid is below:
$ clang-19 --version Debian clang version 19.1.7 (3) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
When I tested with above version with arm64-linux's for-next/fixes including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
Thanks to let me know. But still I've failed to reproduce this on Cortex-a72 and any older cpu on qeum. If you don't mind, would you share your Kconfig?
I haven't debugged it yet but I wonder whether something wants to write this variable after it was made read-only (well, I couldn't find any by grep'ing the code, so it needs some step-by-step debugging).
[...]
Thanks!
-- Sincerely, Yeoreum Yun
On 06/05/2025 09:09, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote:
On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote:
create_init_idmap() could be called before .bss section initialization which is done in early_map_kernel(). Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro.
PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". and this variable places in .bss section.
[...]
Applied to arm64 (for-next/fixes), with some slight tweaking of the comment, thanks!
[1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
$ clang --version Debian clang version 19.1.5 (1) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
I didn't have time to investigate, disassemble etc. I'll have a look next week.
Just for your information. When I see the debian package, clang 19.1.5-1 doesn't supply anymore:
and the default version for sid is below:
$ clang-19 --version Debian clang version 19.1.7 (3) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
When I tested with above version with arm64-linux's for-next/fixes including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
I think this is likely because __ro_after_init is also "ro before init" - i.e. if you try to write to it in the PI code an exception is generated due to it being mapped RO. Looks like early_map_kernel() is writiing to it.
I've noticed a similar problem in the past and it would be nice to fix it so that PI code maps __ro_after_init RW.
Thanks, Ryan
Thanks to let me know. But still I've failed to reproduce this on Cortex-a72 and any older cpu on qeum. If you don't mind, would you share your Kconfig?
I haven't debugged it yet but I wonder whether something wants to write this variable after it was made read-only (well, I couldn't find any by grep'ing the code, so it needs some step-by-step debugging).
[...]
Thanks!
-- Sincerely, Yeoreum Yun
Hi Ryan,
On 06/05/2025 09:09, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote:
On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: > create_init_idmap() could be called before .bss section initialization > which is done in early_map_kernel(). > Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. > > PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". > and this variable places in .bss section. > > [...]
Applied to arm64 (for-next/fixes), with some slight tweaking of the comment, thanks!
[1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
$ clang --version Debian clang version 19.1.5 (1) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
I didn't have time to investigate, disassemble etc. I'll have a look next week.
Just for your information. When I see the debian package, clang 19.1.5-1 doesn't supply anymore:
and the default version for sid is below:
$ clang-19 --version Debian clang version 19.1.7 (3) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
When I tested with above version with arm64-linux's for-next/fixes including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
I think this is likely because __ro_after_init is also "ro before init" - i.e. if you try to write to it in the PI code an exception is generated due to it being mapped RO. Looks like early_map_kernel() is writiing to it.
I've noticed a similar problem in the past and it would be nice to fix it so that PI code maps __ro_after_init RW.
Personally, I don't believe this because the create_init_idmap() maps the the .rodata section with PAGE_KERNEL pgprot from __initdata_begin to _end.
and at the mark_readonly() the pgprot is changed to PAGE_KERNEL_RO But, arm64_use_ng_mappings is accessed with write before mark_readonly() only via smp_cpus_done().
JFYI here is map information:
// mark_readlonly() changes to ro perm below ranges: ffff800081b30000 g .rodata 0000000000000000 __start_rodata ffff800082560000 g .rodata.text 0000000000000000 __init_begin
// create_init_idmap() maps below range with PAGE_KERNEL. ffff8000826d0000 g .altinstructions 0000000000000000 __initdata_begin ffff800082eb0000 g .bss 0000000000000000 _end
ffff8000824596d0 g O .rodata 0000000000000001 arm64_use_ng_mappings
Thanks.
Thanks, Ryan
Thanks to let me know. But still I've failed to reproduce this on Cortex-a72 and any older cpu on qeum. If you don't mind, would you share your Kconfig?
I haven't debugged it yet but I wonder whether something wants to write this variable after it was made read-only (well, I couldn't find any by grep'ing the code, so it needs some step-by-step debugging).
[...]
Thanks!
-- Sincerely, Yeoreum Yun
-- Sincerely, Yeoreum Yun
On Tue, May 06, 2025 at 09:53:57AM +0100, Yeoreum Yun wrote:
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote: > On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: >> create_init_idmap() could be called before .bss section initialization >> which is done in early_map_kernel(). >> Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. >> >> PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". >> and this variable places in .bss section. >> >> [...] > > Applied to arm64 (for-next/fixes), with some slight tweaking of the > comment, thanks! > > [1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation > https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
[...]
Personally, I don't believe this because the create_init_idmap() maps the the .rodata section with PAGE_KERNEL pgprot from __initdata_begin to _end.
and at the mark_readonly() the pgprot is changed to PAGE_KERNEL_RO But, arm64_use_ng_mappings is accessed with write before mark_readonly() only via smp_cpus_done().
JFYI here is map information:
// mark_readlonly() changes to ro perm below ranges: ffff800081b30000 g .rodata 0000000000000000 __start_rodata ffff800082560000 g .rodata.text 0000000000000000 __init_begin
// create_init_idmap() maps below range with PAGE_KERNEL. ffff8000826d0000 g .altinstructions 0000000000000000 __initdata_begin ffff800082eb0000 g .bss 0000000000000000 _end
ffff8000824596d0 g O .rodata 0000000000000001 arm64_use_ng_mappings
So arm64_use_ng_mappings is mapped as read-only since .rodata is before __initdata_begin.
On Tue, May 06, 2025 at 11:12:50AM +0100, Catalin Marinas wrote:
On Tue, May 06, 2025 at 09:53:57AM +0100, Yeoreum Yun wrote:
> On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote: >> On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: >>> create_init_idmap() could be called before .bss section initialization >>> which is done in early_map_kernel(). >>> Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. >>> >>> PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". >>> and this variable places in .bss section. >>> >>> [...] >> >> Applied to arm64 (for-next/fixes), with some slight tweaking of the >> comment, thanks! >> >> [1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation >> https://git.kernel.org/arm64/c/12657bcd1835 > > I'm going to drop this for now. The kernel compiled with a clang 19.1.5 > version I have around (Debian sid) fails to boot, gets stuck early on:
[...]
Personally, I don't believe this because the create_init_idmap() maps the the .rodata section with PAGE_KERNEL pgprot from __initdata_begin to _end.
and at the mark_readonly() the pgprot is changed to PAGE_KERNEL_RO But, arm64_use_ng_mappings is accessed with write before mark_readonly() only via smp_cpus_done().
JFYI here is map information:
// mark_readlonly() changes to ro perm below ranges: ffff800081b30000 g .rodata 0000000000000000 __start_rodata ffff800082560000 g .rodata.text 0000000000000000 __init_begin
// create_init_idmap() maps below range with PAGE_KERNEL. ffff8000826d0000 g .altinstructions 0000000000000000 __initdata_begin ffff800082eb0000 g .bss 0000000000000000 _end
ffff8000824596d0 g O .rodata 0000000000000001 arm64_use_ng_mappings
So arm64_use_ng_mappings is mapped as read-only since .rodata is before __initdata_begin.
Right. I've misread teh address at first time. Sorry to make noise.
-- Catalin
-- Sincerely, Yeoreum Yun
On 06/05/2025 09:53, Yeoreum Yun wrote:
Hi Ryan,
On 06/05/2025 09:09, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote: > On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: >> create_init_idmap() could be called before .bss section initialization >> which is done in early_map_kernel(). >> Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. >> >> PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". >> and this variable places in .bss section. >> >> [...] > > Applied to arm64 (for-next/fixes), with some slight tweaking of the > comment, thanks! > > [1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation > https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
$ clang --version Debian clang version 19.1.5 (1) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
I didn't have time to investigate, disassemble etc. I'll have a look next week.
Just for your information. When I see the debian package, clang 19.1.5-1 doesn't supply anymore:
and the default version for sid is below:
$ clang-19 --version Debian clang version 19.1.7 (3) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
When I tested with above version with arm64-linux's for-next/fixes including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
I think this is likely because __ro_after_init is also "ro before init" - i.e. if you try to write to it in the PI code an exception is generated due to it being mapped RO. Looks like early_map_kernel() is writiing to it.
I've noticed a similar problem in the past and it would be nice to fix it so that PI code maps __ro_after_init RW.
Personally, I don't believe this because the create_init_idmap() maps the the .rodata section with PAGE_KERNEL pgprot from __initdata_begin to _end.
But __ro_after_init is in the ".data..ro_after_init" section, which is in the .rodata section. That's mapped PAGE_KERNEL_ROX as Ard says.
and at the mark_readonly() the pgprot is changed to PAGE_KERNEL_RO But, arm64_use_ng_mappings is accessed with write before mark_readonly() only via smp_cpus_done().
JFYI here is map information:
// mark_readlonly() changes to ro perm below ranges: ffff800081b30000 g .rodata 0000000000000000 __start_rodata ffff800082560000 g .rodata.text 0000000000000000 __init_begin
// create_init_idmap() maps below range with PAGE_KERNEL. ffff8000826d0000 g .altinstructions 0000000000000000 __initdata_begin ffff800082eb0000 g .bss 0000000000000000 _end
ffff8000824596d0 g O .rodata 0000000000000001 arm64_use_ng_mappings
Thanks.
Thanks, Ryan
Thanks to let me know. But still I've failed to reproduce this on Cortex-a72 and any older cpu on qeum. If you don't mind, would you share your Kconfig?
I haven't debugged it yet but I wonder whether something wants to write this variable after it was made read-only (well, I couldn't find any by grep'ing the code, so it needs some step-by-step debugging).
[...]
Thanks!
-- Sincerely, Yeoreum Yun
-- Sincerely, Yeoreum Yun
On Tue, 6 May 2025 at 10:16, Ryan Roberts ryan.roberts@arm.com wrote:
On 06/05/2025 09:09, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote:
On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: > create_init_idmap() could be called before .bss section initialization > which is done in early_map_kernel(). > Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. > > PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". > and this variable places in .bss section. > > [...]
Applied to arm64 (for-next/fixes), with some slight tweaking of the comment, thanks!
[1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
$ clang --version Debian clang version 19.1.5 (1) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
I didn't have time to investigate, disassemble etc. I'll have a look next week.
Just for your information. When I see the debian package, clang 19.1.5-1 doesn't supply anymore:
and the default version for sid is below:
$ clang-19 --version Debian clang version 19.1.7 (3) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
When I tested with above version with arm64-linux's for-next/fixes including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
I think this is likely because __ro_after_init is also "ro before init" - i.e. if you try to write to it in the PI code an exception is generated due to it being mapped RO. Looks like early_map_kernel() is writiing to it.
Indeed.
I've noticed a similar problem in the past and it would be nice to fix it so that PI code maps __ro_after_init RW.
The issue is that the store occurs via the ID map, which only consists of one R-X and one RW- section. I'm not convinced that it's worth the hassle to relax this.
If moving the variable to .data works, then let's just do that.
On 06/05/2025 10:41, Ard Biesheuvel wrote:
On Tue, 6 May 2025 at 10:16, Ryan Roberts ryan.roberts@arm.com wrote:
On 06/05/2025 09:09, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote: > On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: >> create_init_idmap() could be called before .bss section initialization >> which is done in early_map_kernel(). >> Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. >> >> PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". >> and this variable places in .bss section. >> >> [...] > > Applied to arm64 (for-next/fixes), with some slight tweaking of the > comment, thanks! > > [1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation > https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
$ clang --version Debian clang version 19.1.5 (1) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
I didn't have time to investigate, disassemble etc. I'll have a look next week.
Just for your information. When I see the debian package, clang 19.1.5-1 doesn't supply anymore:
and the default version for sid is below:
$ clang-19 --version Debian clang version 19.1.7 (3) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
When I tested with above version with arm64-linux's for-next/fixes including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
I think this is likely because __ro_after_init is also "ro before init" - i.e. if you try to write to it in the PI code an exception is generated due to it being mapped RO. Looks like early_map_kernel() is writiing to it.
Indeed.
I've noticed a similar problem in the past and it would be nice to fix it so that PI code maps __ro_after_init RW.
The issue is that the store occurs via the ID map, which only consists of one R-X and one RW- section. I'm not convinced that it's worth the hassle to relax this.
If moving the variable to .data works, then let's just do that.
Yeah, fair enough.
On 06/05/2025 10:41, Ard Biesheuvel wrote:
On Tue, 6 May 2025 at 10:16, Ryan Roberts ryan.roberts@arm.com wrote:
On 06/05/2025 09:09, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote:
Hi Catalin,
> On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote: >> On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: >>> create_init_idmap() could be called before .bss section initialization >>> which is done in early_map_kernel(). >>> Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. >>> >>> PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". >>> and this variable places in .bss section. >>> >>> [...] >> >> Applied to arm64 (for-next/fixes), with some slight tweaking of the >> comment, thanks! >> >> [1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation >> https://git.kernel.org/arm64/c/12657bcd1835 > > I'm going to drop this for now. The kernel compiled with a clang 19.1.5 > version I have around (Debian sid) fails to boot, gets stuck early on: > > $ clang --version > Debian clang version 19.1.5 (1) > Target: aarch64-unknown-linux-gnu > Thread model: posix > InstalledDir: /usr/lib/llvm-19/bin > > I didn't have time to investigate, disassemble etc. I'll have a look > next week.
Just for your information. When I see the debian package, clang 19.1.5-1 doesn't supply anymore:
and the default version for sid is below:
$ clang-19 --version Debian clang version 19.1.7 (3) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
When I tested with above version with arm64-linux's for-next/fixes including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
I think this is likely because __ro_after_init is also "ro before init" - i.e. if you try to write to it in the PI code an exception is generated due to it being mapped RO. Looks like early_map_kernel() is writiing to it.
Indeed.
I've noticed a similar problem in the past and it would be nice to fix it so that PI code maps __ro_after_init RW.
The issue is that the store occurs via the ID map, which only consists of one R-X and one RW- section. I'm not convinced that it's worth the hassle to relax this.
If moving the variable to .data works, then let's just do that.
Yeah, fair enough.
Thanks. I've success to reproduce. and after check, Sending with this fix.
-- Sincerely, Yeoreum Yun
On Tue, May 06, 2025 at 11:47:44AM +0100, Yeoreum Yun wrote:
On 06/05/2025 10:41, Ard Biesheuvel wrote:
On Tue, 6 May 2025 at 10:16, Ryan Roberts ryan.roberts@arm.com wrote:
On 06/05/2025 09:09, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote: > Hi Catalin, > >> On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote: >>> On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: >>>> create_init_idmap() could be called before .bss section initialization >>>> which is done in early_map_kernel(). >>>> Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. >>>> >>>> PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". >>>> and this variable places in .bss section. >>>> >>>> [...] >>> >>> Applied to arm64 (for-next/fixes), with some slight tweaking of the >>> comment, thanks! >>> >>> [1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation >>> https://git.kernel.org/arm64/c/12657bcd1835 >> >> I'm going to drop this for now. The kernel compiled with a clang 19.1.5 >> version I have around (Debian sid) fails to boot, gets stuck early on: >> >> $ clang --version >> Debian clang version 19.1.5 (1) >> Target: aarch64-unknown-linux-gnu >> Thread model: posix >> InstalledDir: /usr/lib/llvm-19/bin >> >> I didn't have time to investigate, disassemble etc. I'll have a look >> next week. > > Just for your information. > When I see the debian package, clang 19.1.5-1 doesn't supply anymore: > - https://ftp.debian.org/debian/pool/main/l/llvm-toolchain-19/ > > and the default version for sid is below: > > $ clang-19 --version > Debian clang version 19.1.7 (3) > Target: aarch64-unknown-linux-gnu > Thread model: posix > InstalledDir: /usr/lib/llvm-19/bin > > When I tested with above version with arm64-linux's for-next/fixes > including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
I think this is likely because __ro_after_init is also "ro before init" - i.e. if you try to write to it in the PI code an exception is generated due to it being mapped RO. Looks like early_map_kernel() is writiing to it.
Indeed.
I've noticed a similar problem in the past and it would be nice to fix it so that PI code maps __ro_after_init RW.
The issue is that the store occurs via the ID map, which only consists of one R-X and one RW- section. I'm not convinced that it's worth the hassle to relax this.
If moving the variable to .data works, then let's just do that.
Yeah, fair enough.
Thanks. I've success to reproduce. and after check, Sending with this fix.
No need to resend, I modified it locally. Thanks.
On Tue, May 06, 2025 at 11:47:44AM +0100, Yeoreum Yun wrote:
On 06/05/2025 10:41, Ard Biesheuvel wrote:
On Tue, 6 May 2025 at 10:16, Ryan Roberts ryan.roberts@arm.com wrote:
On 06/05/2025 09:09, Yeoreum Yun wrote:
Hi Catalin,
> On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote: >> Hi Catalin, >> >>> On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote: >>>> On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: >>>>> create_init_idmap() could be called before .bss section initialization >>>>> which is done in early_map_kernel(). >>>>> Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. >>>>> >>>>> PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". >>>>> and this variable places in .bss section. >>>>> >>>>> [...] >>>> >>>> Applied to arm64 (for-next/fixes), with some slight tweaking of the >>>> comment, thanks! >>>> >>>> [1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation >>>> https://git.kernel.org/arm64/c/12657bcd1835 >>> >>> I'm going to drop this for now. The kernel compiled with a clang 19.1.5 >>> version I have around (Debian sid) fails to boot, gets stuck early on: >>> >>> $ clang --version >>> Debian clang version 19.1.5 (1) >>> Target: aarch64-unknown-linux-gnu >>> Thread model: posix >>> InstalledDir: /usr/lib/llvm-19/bin >>> >>> I didn't have time to investigate, disassemble etc. I'll have a look >>> next week. >> >> Just for your information. >> When I see the debian package, clang 19.1.5-1 doesn't supply anymore: >> - https://ftp.debian.org/debian/pool/main/l/llvm-toolchain-19/ >> >> and the default version for sid is below: >> >> $ clang-19 --version >> Debian clang version 19.1.7 (3) >> Target: aarch64-unknown-linux-gnu >> Thread model: posix >> InstalledDir: /usr/lib/llvm-19/bin >> >> When I tested with above version with arm64-linux's for-next/fixes >> including this patch. it works well. > > It doesn't seem to be toolchain related. It fails with gcc as well from > Debian stable but you'd need some older CPU (even if emulated, e.g. > qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not > Neoverse-N2. Also changing the annotation from __ro_after_init to > __read_mostly also works.
I think this is likely because __ro_after_init is also "ro before init" - i.e. if you try to write to it in the PI code an exception is generated due to it being mapped RO. Looks like early_map_kernel() is writiing to it.
Indeed.
I've noticed a similar problem in the past and it would be nice to fix it so that PI code maps __ro_after_init RW.
The issue is that the store occurs via the ID map, which only consists of one R-X and one RW- section. I'm not convinced that it's worth the hassle to relax this.
If moving the variable to .data works, then let's just do that.
Yeah, fair enough.
Thanks. I've success to reproduce. and after check, Sending with this fix.
No need to resend, I modified it locally. Thanks.
Thanks. and Sorry to all for making this because of my lack :\
-- Sincerely, Yeoreum Yun
On Tue, May 06, 2025 at 11:41:05AM +0200, Ard Biesheuvel wrote:
On Tue, 6 May 2025 at 10:16, Ryan Roberts ryan.roberts@arm.com wrote:
On 06/05/2025 09:09, Yeoreum Yun wrote:
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote:
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote: > On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: >> create_init_idmap() could be called before .bss section initialization >> which is done in early_map_kernel(). >> Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. >> >> PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". >> and this variable places in .bss section. >> >> [...] > > Applied to arm64 (for-next/fixes), with some slight tweaking of the > comment, thanks! > > [1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation > https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
$ clang --version Debian clang version 19.1.5 (1) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
I didn't have time to investigate, disassemble etc. I'll have a look next week.
Just for your information. When I see the debian package, clang 19.1.5-1 doesn't supply anymore:
and the default version for sid is below:
$ clang-19 --version Debian clang version 19.1.7 (3) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
When I tested with above version with arm64-linux's for-next/fixes including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
I think this is likely because __ro_after_init is also "ro before init" - i.e. if you try to write to it in the PI code an exception is generated due to it being mapped RO. Looks like early_map_kernel() is writiing to it.
Indeed.
I've noticed a similar problem in the past and it would be nice to fix it so that PI code maps __ro_after_init RW.
The issue is that the store occurs via the ID map, which only consists of one R-X and one RW- section. I'm not convinced that it's worth the hassle to relax this.
If moving the variable to .data works, then let's just do that.
Good to know there's no other more serious issue. I'll move this variable to __read_mostly.
It seems to fail in early_map_kernel() if RANDOMIZE_BASE is enabled.
On 06/05/2025 11:17, Catalin Marinas wrote:
On Tue, May 06, 2025 at 11:41:05AM +0200, Ard Biesheuvel wrote:
On Tue, 6 May 2025 at 10:16, Ryan Roberts ryan.roberts@arm.com wrote:
On 06/05/2025 09:09, Yeoreum Yun wrote:
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote:
> On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote: >> On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: >>> create_init_idmap() could be called before .bss section initialization >>> which is done in early_map_kernel(). >>> Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. >>> >>> PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". >>> and this variable places in .bss section. >>> >>> [...] >> >> Applied to arm64 (for-next/fixes), with some slight tweaking of the >> comment, thanks! >> >> [1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation >> https://git.kernel.org/arm64/c/12657bcd1835 > > I'm going to drop this for now. The kernel compiled with a clang 19.1.5 > version I have around (Debian sid) fails to boot, gets stuck early on: > > $ clang --version > Debian clang version 19.1.5 (1) > Target: aarch64-unknown-linux-gnu > Thread model: posix > InstalledDir: /usr/lib/llvm-19/bin > > I didn't have time to investigate, disassemble etc. I'll have a look > next week.
Just for your information. When I see the debian package, clang 19.1.5-1 doesn't supply anymore:
and the default version for sid is below:
$ clang-19 --version Debian clang version 19.1.7 (3) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
When I tested with above version with arm64-linux's for-next/fixes including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
I think this is likely because __ro_after_init is also "ro before init" - i.e. if you try to write to it in the PI code an exception is generated due to it being mapped RO. Looks like early_map_kernel() is writiing to it.
Indeed.
I've noticed a similar problem in the past and it would be nice to fix it so that PI code maps __ro_after_init RW.
The issue is that the store occurs via the ID map, which only consists of one R-X and one RW- section. I'm not convinced that it's worth the hassle to relax this.
If moving the variable to .data works, then let's just do that.
Good to know there's no other more serious issue. I'll move this variable to __read_mostly.
It seems to fail in early_map_kernel() if RANDOMIZE_BASE is enabled.
Ahh that explains why Yeoreum Yun can't see the issue:
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { u64 kaslr_seed = kaslr_early_init(fdt, chosen);
if (kaslr_seed && kaslr_requires_kpti()) arm64_use_ng_mappings = true;
kaslr_offset |= kaslr_seed & ~(MIN_KIMG_ALIGN - 1); }
On Tue, May 06, 2025 at 11:22:47AM +0100, Ryan Roberts wrote:
On 06/05/2025 11:17, Catalin Marinas wrote:
On Tue, May 06, 2025 at 11:41:05AM +0200, Ard Biesheuvel wrote:
On Tue, 6 May 2025 at 10:16, Ryan Roberts ryan.roberts@arm.com wrote:
On 06/05/2025 09:09, Yeoreum Yun wrote:
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote: >> On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote: >>> On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: >>>> create_init_idmap() could be called before .bss section initialization >>>> which is done in early_map_kernel(). >>>> Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. >>>> >>>> PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". >>>> and this variable places in .bss section. >>>> >>>> [...] >>> >>> Applied to arm64 (for-next/fixes), with some slight tweaking of the >>> comment, thanks! >>> >>> [1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation >>> https://git.kernel.org/arm64/c/12657bcd1835 >> >> I'm going to drop this for now. The kernel compiled with a clang 19.1.5 >> version I have around (Debian sid) fails to boot, gets stuck early on: >> >> $ clang --version >> Debian clang version 19.1.5 (1) >> Target: aarch64-unknown-linux-gnu >> Thread model: posix >> InstalledDir: /usr/lib/llvm-19/bin >> >> I didn't have time to investigate, disassemble etc. I'll have a look >> next week. > > Just for your information. > When I see the debian package, clang 19.1.5-1 doesn't supply anymore: > - https://ftp.debian.org/debian/pool/main/l/llvm-toolchain-19/ > > and the default version for sid is below: > > $ clang-19 --version > Debian clang version 19.1.7 (3) > Target: aarch64-unknown-linux-gnu > Thread model: posix > InstalledDir: /usr/lib/llvm-19/bin > > When I tested with above version with arm64-linux's for-next/fixes > including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
I think this is likely because __ro_after_init is also "ro before init" - i.e. if you try to write to it in the PI code an exception is generated due to it being mapped RO. Looks like early_map_kernel() is writiing to it.
Indeed.
I've noticed a similar problem in the past and it would be nice to fix it so that PI code maps __ro_after_init RW.
The issue is that the store occurs via the ID map, which only consists of one R-X and one RW- section. I'm not convinced that it's worth the hassle to relax this.
If moving the variable to .data works, then let's just do that.
Good to know there's no other more serious issue. I'll move this variable to __read_mostly.
It seems to fail in early_map_kernel() if RANDOMIZE_BASE is enabled.
Ahh that explains why Yeoreum Yun can't see the issue:
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { u64 kaslr_seed = kaslr_early_init(fdt, chosen);
if (kaslr_seed && kaslr_requires_kpti()) arm64_use_ng_mappings = true; kaslr_offset |= kaslr_seed & ~(MIN_KIMG_ALIGN - 1);
}
Yeah, you may need this as well for qemu:
-object rng-random,filename=/dev/urandom,id=rng0 \ -device virtio-rng-pci,rng=rng0 \
BTW, some architectures have RO_DATA immediately after _sdata but for us it messes up some of the contig mappings, so the safest is to move the variable to the .data section.
Hi Ryan,
On 06/05/2025 11:17, Catalin Marinas wrote:
On Tue, May 06, 2025 at 11:41:05AM +0200, Ard Biesheuvel wrote:
On Tue, 6 May 2025 at 10:16, Ryan Roberts ryan.roberts@arm.com wrote:
On 06/05/2025 09:09, Yeoreum Yun wrote:
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote: >> On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote: >>> On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote: >>>> create_init_idmap() could be called before .bss section initialization >>>> which is done in early_map_kernel(). >>>> Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro. >>>> >>>> PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". >>>> and this variable places in .bss section. >>>> >>>> [...] >>> >>> Applied to arm64 (for-next/fixes), with some slight tweaking of the >>> comment, thanks! >>> >>> [1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation >>> https://git.kernel.org/arm64/c/12657bcd1835 >> >> I'm going to drop this for now. The kernel compiled with a clang 19.1.5 >> version I have around (Debian sid) fails to boot, gets stuck early on: >> >> $ clang --version >> Debian clang version 19.1.5 (1) >> Target: aarch64-unknown-linux-gnu >> Thread model: posix >> InstalledDir: /usr/lib/llvm-19/bin >> >> I didn't have time to investigate, disassemble etc. I'll have a look >> next week. > > Just for your information. > When I see the debian package, clang 19.1.5-1 doesn't supply anymore: > - https://ftp.debian.org/debian/pool/main/l/llvm-toolchain-19/ > > and the default version for sid is below: > > $ clang-19 --version > Debian clang version 19.1.7 (3) > Target: aarch64-unknown-linux-gnu > Thread model: posix > InstalledDir: /usr/lib/llvm-19/bin > > When I tested with above version with arm64-linux's for-next/fixes > including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
I think this is likely because __ro_after_init is also "ro before init" - i.e. if you try to write to it in the PI code an exception is generated due to it being mapped RO. Looks like early_map_kernel() is writiing to it.
Indeed.
I've noticed a similar problem in the past and it would be nice to fix it so that PI code maps __ro_after_init RW.
The issue is that the store occurs via the ID map, which only consists of one R-X and one RW- section. I'm not convinced that it's worth the hassle to relax this.
If moving the variable to .data works, then let's just do that.
Good to know there's no other more serious issue. I'll move this variable to __read_mostly.
It seems to fail in early_map_kernel() if RANDOMIZE_BASE is enabled.
Ahh that explains why Yeoreum Yun can't see the issue:
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { u64 kaslr_seed = kaslr_early_init(fdt, chosen);
if (kaslr_seed && kaslr_requires_kpti()) arm64_use_ng_mappings = true; kaslr_offset |= kaslr_seed & ~(MIN_KIMG_ALIGN - 1);
}
Thanks to clarify me to know. I've misread the address of arm64_use_ng_mapping :( so my brain works wrong.
Thanks again!
-- Sincerely, Yeoreum Yun
On Tue, May 06, 2025 at 09:09:14AM +0100, Yeoreum Yun wrote:
On Sat, May 03, 2025 at 09:23:27PM +0100, Yeoreum Yun wrote:
Hi Catalin,
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote:
On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote:
create_init_idmap() could be called before .bss section initialization which is done in early_map_kernel(). Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro.
PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". and this variable places in .bss section.
[...]
Applied to arm64 (for-next/fixes), with some slight tweaking of the comment, thanks!
[1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
$ clang --version Debian clang version 19.1.5 (1) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
I didn't have time to investigate, disassemble etc. I'll have a look next week.
Just for your information. When I see the debian package, clang 19.1.5-1 doesn't supply anymore:
and the default version for sid is below:
$ clang-19 --version Debian clang version 19.1.7 (3) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
When I tested with above version with arm64-linux's for-next/fixes including this patch. it works well.
It doesn't seem to be toolchain related. It fails with gcc as well from Debian stable but you'd need some older CPU (even if emulated, e.g. qemu). It fails with Cortex-A72 (guest on Raspberry Pi 4) but not Neoverse-N2. Also changing the annotation from __ro_after_init to __read_mostly also works.
Thanks to let me know. But still I've failed to reproduce this on Cortex-a72 and any older cpu on qeum. If you don't mind, would you share your Kconfig?
Just defconfig with gcc (Debian 12.2.0-14) 12.2.0. It fails for me with "qemu -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd -cpu cortex-a53" (I have qemu 9.1.1 around, I don't think that's relevant).
On Sat, May 03, 2025 at 03:11:36PM +0100, Catalin Marinas wrote:
On Sat, May 03, 2025 at 11:16:12AM +0100, Catalin Marinas wrote:
On Fri, 02 May 2025 19:04:12 +0100, Yeoreum Yun wrote:
create_init_idmap() could be called before .bss section initialization which is done in early_map_kernel(). Therefore, data/test_prot could be set incorrectly by PTE_MAYBE_NG macro.
PTE_MAYBE_NG macro set NG bit according to value of "arm64_use_ng_mappings". and this variable places in .bss section.
[...]
Applied to arm64 (for-next/fixes), with some slight tweaking of the comment, thanks!
[1/1] arm64/cpufeature: annotate arm64_use_ng_mappings with ro_after_init to prevent wrong idmap generation https://git.kernel.org/arm64/c/12657bcd1835
I'm going to drop this for now. The kernel compiled with a clang 19.1.5 version I have around (Debian sid) fails to boot, gets stuck early on:
$ clang --version Debian clang version 19.1.5 (1) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/lib/llvm-19/bin
I reinstated the patch with __read_mostly and some rewriting of the commit message (I left out the gcc code generation, it's just luck that we have not hit it before). That's the new commit on the arm64 for-next/fixes branch:
[1/1] arm64: cpufeature: Move arm64_use_ng_mappings to the .data section to prevent wrong idmap generation https://git.kernel.org/arm64/c/363cd2b81cfd
I kept the original tested-by from Nathan, I reckon the patch still works ;).
Thanks.
linux-stable-mirror@lists.linaro.org