[v2,0/5] LoongArch: Add kernel relocation and KASLR support

Message ID 20230207142822.52172-1-xry111@xry111.site
Headers
Series LoongArch: Add kernel relocation and KASLR support |

Message

Xi Ruoyao Feb. 7, 2023, 2:28 p.m. UTC
  This patch series to support kernel relocation and KASLR (only 64bit).

I've only tested new toolchains (CONFIG_AS_HAS_EXPLICIT_RELOCS=y)
consisted of Binutils-2.40, and GCC-12.2 heavily patched to support new
relocs.  Unfortunately I've purged my old toolchain installation (because
it contained a buggy GCC-12.1 miscompiling some code).  Please test the
configuration with old toolchain.

Test results with CONFIG_RANDOMIZE_BASE=y on a 3A5000-7A2000-EVB:

First boot:

$ sudo cat /proc/iomem | grep Kernel
  010e0000-018fffff : Kernel code
  01900000-01e4b5ff : Kernel data
  01e4b600-01f56e9f : Kernel bss

Second boot:

$ sudo cat /proc/iomem | grep Kernel
  019a0000-021bffff : Kernel code
  021c0000-0270b5ff : Kernel data
  0270b600-02816e9f : Kernel bss

Changes from v1:

- Relocate the handlers instead of using a trampoline, to avoid
  performance issue on NUMA systems.
- Fix compiler warnings.

Xi Ruoyao (2):
  LoongArch: Use la.pcrel instead of la.abs when it's trivially possible
  LoongArch: Use la.pcrel instead of la.abs for exception handlers

Youling Tang (3):
  LoongArch: Add JUMP_LINK_ADDR macro implementation to avoid using
    la.abs
  LoongArch: Add support for kernel relocation
  LoongArch: Add support for kernel address space layout randomization
    (KASLR)

 arch/loongarch/Kconfig                  |  37 +++++
 arch/loongarch/Makefile                 |   5 +
 arch/loongarch/include/asm/page.h       |   6 +
 arch/loongarch/include/asm/setup.h      |   6 +-
 arch/loongarch/include/asm/stackframe.h |  13 +-
 arch/loongarch/include/asm/uaccess.h    |   1 -
 arch/loongarch/kernel/Makefile          |   2 +
 arch/loongarch/kernel/entry.S           |   2 +-
 arch/loongarch/kernel/genex.S           |  40 ++++-
 arch/loongarch/kernel/head.S            |  30 +++-
 arch/loongarch/kernel/relocate.c        | 211 ++++++++++++++++++++++++
 arch/loongarch/kernel/setup.c           |   3 +
 arch/loongarch/kernel/traps.c           | 138 +++++++++++++---
 arch/loongarch/kernel/vmlinux.lds.S     |  11 +-
 arch/loongarch/mm/tlb.c                 |  23 +--
 arch/loongarch/mm/tlbex.S               |  72 +++++++-
 arch/loongarch/power/suspend_asm.S      |   5 +-
 17 files changed, 543 insertions(+), 62 deletions(-)
 create mode 100644 arch/loongarch/kernel/relocate.c
  

Comments

Youling Tang Feb. 8, 2023, 4:37 a.m. UTC | #1
Hi, Ruoyao

On 02/07/2023 10:28 PM, Xi Ruoyao wrote:
> This patch series to support kernel relocation and KASLR (only 64bit).
>
> I've only tested new toolchains (CONFIG_AS_HAS_EXPLICIT_RELOCS=y)
> consisted of Binutils-2.40, and GCC-12.2 heavily patched to support new
> relocs.  Unfortunately I've purged my old toolchain installation (because
> it contained a buggy GCC-12.1 miscompiling some code).  Please test the
> configuration with old toolchain.
I tested it through QEMU.

Testing in the new toolchains is successful,
/ # dmesg | head
[    0.000000] Linux version 6.2.0-rc7+ (root@bogon) 
(loongarch64-unknown-linux-gnu-gcc (GCC) 13.0.0 20220906 (experimental), 
GNU ld (GNU Binutils) 2.39.50.20220906) #67 SMP PREEMPT Wed Feb  8 
09:42:49 CST 2023
/ # cat /proc/iomem | head
00000000-0fffffff : System RAM
   00000000-002c3fff : Reserved
   002c4000-008c3fff : Reserved
   02a50000-0399ffff : Kernel code
   039a0000-0426d9ff : Kernel data
   0426da00-0439ae37 : Kernel bss


But testing in the old toolchains failed, stuck in the following
position,
[    0.000000] Linux version 6.2.0-rc7+ (root@bogon) 
(loongarch64-unknown-linux-gnu-gcc (GCC) 12.1.0, GNU ld (GNU Binutils) 
2.38.50.20220519) #68 SMP PREEMPT Wed Feb  8 09:52:49 CST 2023
...
[    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on 
contention.
[    0.000000] Constant clock event device register
[    0.000000] clocksource: Constant: mask: 0xffffffffffffffff 
max_cycles: 0x171024e7e0, max_idle_ns: 440795205315 ns
[    0.000289] sched_clock: 64 bits at 100MHz, resolution 10ns, wraps 
every 4398046511100ns
[    0.000715] Constant clock source device register


In the case of "[Patch v2 2/5] LoongArch: use la.pcrel instenad of
la.abs for exception handlerS", the above failure will occur.

Patch2 may have certain problems when using the old toolchains.

Youling.

>
> Test results with CONFIG_RANDOMIZE_BASE=y on a 3A5000-7A2000-EVB:
>
> First boot:
>
> $ sudo cat /proc/iomem | grep Kernel
>   010e0000-018fffff : Kernel code
>   01900000-01e4b5ff : Kernel data
>   01e4b600-01f56e9f : Kernel bss
>
> Second boot:
>
> $ sudo cat /proc/iomem | grep Kernel
>   019a0000-021bffff : Kernel code
>   021c0000-0270b5ff : Kernel data
>   0270b600-02816e9f : Kernel bss
>
> Changes from v1:
>
> - Relocate the handlers instead of using a trampoline, to avoid
>   performance issue on NUMA systems.
> - Fix compiler warnings.
>
> Xi Ruoyao (2):
>   LoongArch: Use la.pcrel instead of la.abs when it's trivially possible
>   LoongArch: Use la.pcrel instead of la.abs for exception handlers
>
> Youling Tang (3):
>   LoongArch: Add JUMP_LINK_ADDR macro implementation to avoid using
>     la.abs
>   LoongArch: Add support for kernel relocation
>   LoongArch: Add support for kernel address space layout randomization
>     (KASLR)
>
>  arch/loongarch/Kconfig                  |  37 +++++
>  arch/loongarch/Makefile                 |   5 +
>  arch/loongarch/include/asm/page.h       |   6 +
>  arch/loongarch/include/asm/setup.h      |   6 +-
>  arch/loongarch/include/asm/stackframe.h |  13 +-
>  arch/loongarch/include/asm/uaccess.h    |   1 -
>  arch/loongarch/kernel/Makefile          |   2 +
>  arch/loongarch/kernel/entry.S           |   2 +-
>  arch/loongarch/kernel/genex.S           |  40 ++++-
>  arch/loongarch/kernel/head.S            |  30 +++-
>  arch/loongarch/kernel/relocate.c        | 211 ++++++++++++++++++++++++
>  arch/loongarch/kernel/setup.c           |   3 +
>  arch/loongarch/kernel/traps.c           | 138 +++++++++++++---
>  arch/loongarch/kernel/vmlinux.lds.S     |  11 +-
>  arch/loongarch/mm/tlb.c                 |  23 +--
>  arch/loongarch/mm/tlbex.S               |  72 +++++++-
>  arch/loongarch/power/suspend_asm.S      |   5 +-
>  17 files changed, 543 insertions(+), 62 deletions(-)
>  create mode 100644 arch/loongarch/kernel/relocate.c
>
  
Xi Ruoyao Feb. 8, 2023, 8:27 a.m. UTC | #2
On Wed, 2023-02-08 at 12:37 +0800, Youling Tang wrote:
> In the case of "[Patch v2 2/5] LoongArch: use la.pcrel instenad of
> la.abs for exception handlerS", the above failure will occur.
> 
> Patch2 may have certain problems when using the old toolchains.
> 
> Youling.

Thanks for the test...

The problem is: old toolchain uses pcaddu12i/ori/lu32i.d/lu52i.d/add.d
for a 3-operand la.pcrel, while the new toolchain uses
pcalau12i/addi.d/lu32i/lu52i/add.d.  (I've somehow forgotten all the
difference!)

We can fix it with something like...

> +void reloc_handler(unsigned long handler, struct handler_reloc *rel)
> +{
> +	if (!rel)
> +		return;
> +
> +	for (unsigned long i = 0; i < rel->cnt; i++) {
> +		unsigned long pc = handler + rel->entries[i].offset;
> +		unsigned long v = rel->entries[i].sym;

                /* anchor etc. moved into do_reloc_pcalau12i */

> +		union loongarch_instruction *insn =
> +			(union loongarch_instruction *)pc;

                switch insn[0]->reg1i20_format->reg1i20_format {
                case pcaddu12i_op:
                        do_reloc_pcaddu12i(insn, pc, v);
                        break;
                case pcalau12i_op: /* TODO: add it for asm/inst.h */
                        do_reloc_pcalau12i(insn, pc, v);
                        break;
                default:
                        panic("what the f**k");
                }

Alternatively, we can also emit the pcalau12i/addi.d/lu32i/lu52i
sequence and overwrite the pcaddu12i/ori sequence generated by the old
toolchain.

Which way do you like?
  
Youling Tang Feb. 9, 2023, 6:34 a.m. UTC | #3
On 02/08/2023 04:27 PM, Xi Ruoyao wrote:
> On Wed, 2023-02-08 at 12:37 +0800, Youling Tang wrote:
>> In the case of "[Patch v2 2/5] LoongArch: use la.pcrel instenad of
>> la.abs for exception handlerS", the above failure will occur.
>>
>> Patch2 may have certain problems when using the old toolchains.
>>
>> Youling.
>
> Thanks for the test...
>
> The problem is: old toolchain uses pcaddu12i/ori/lu32i.d/lu52i.d/add.d
> for a 3-operand la.pcrel, while the new toolchain uses
> pcalau12i/addi.d/lu32i/lu52i/add.d.  (I've somehow forgotten all the
> difference!)
>
> We can fix it with something like...
>
>> +void reloc_handler(unsigned long handler, struct handler_reloc *rel)
>> +{
>> +	if (!rel)
>> +		return;
>> +
>> +	for (unsigned long i = 0; i < rel->cnt; i++) {
>> +		unsigned long pc = handler + rel->entries[i].offset;
>> +		unsigned long v = rel->entries[i].sym;
>
>                 /* anchor etc. moved into do_reloc_pcalau12i */
>
>> +		union loongarch_instruction *insn =
>> +			(union loongarch_instruction *)pc;
>
>                 switch insn[0]->reg1i20_format->reg1i20_format {
>                 case pcaddu12i_op:
>                         do_reloc_pcaddu12i(insn, pc, v);
>                         break;
>                 case pcalau12i_op: /* TODO: add it for asm/inst.h */
>                         do_reloc_pcalau12i(insn, pc, v);
>                         break;
>                 default:
>                         panic("what the f**k");
>                 }
>
> Alternatively, we can also emit the pcalau12i/addi.d/lu32i/lu52i
> sequence and overwrite the pcaddu12i/ori sequence generated by the old
> toolchain.
>
> Which way do you like?

v3 tested successfully in both new and old toolchains.

Youling.
>