Received: by 2002:a05:6a10:d5a5:0:0:0:0 with SMTP id gn37csp3439500pxb; Sat, 9 Oct 2021 10:22:33 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxAm7akGQ7DqIYE1mOLc64zm09jaD4FxZakHgV8k3WSWDwqrl8WPheMx1kZ3k/P3fQGyrG8 X-Received: by 2002:a17:902:da83:b0:13f:704:d731 with SMTP id j3-20020a170902da8300b0013f0704d731mr14652805plx.77.1633800152797; Sat, 09 Oct 2021 10:22:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1633800152; cv=none; d=google.com; s=arc-20160816; b=Q07twjlXrasqq89nU9hkoJGNYQ28I0MF8W2/ghou2mc7+rRWSmPfeQOSYVdOFexCfi gioaHh8Ma1e7k6i1aAvnxDfpwvzUhlay9dYUlZzKVtrFa1vMfrmrkvZtaau9hg9aIDeE hn4whUne6YZGYHCSSm1sFI8oiUhtWMV7lnseOsWgZuVY4HE6FHLI49Ut/YydV9ikF0fI EoqCEDDcFIV400IHqOiW+P/xmhvg5iLjcomUSgRFbobkxcA+ykD44qgxZfrZGPmFQXYP AvJ3S1hNQT0zErGSBa9jRdldjKD7+RnuJDrLCgw7oU44uTzK8xtKttqRjCf4GKS/raZJ cXPA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-language:content-transfer-encoding :in-reply-to:mime-version:user-agent:date:message-id:from:references :to:subject; bh=OP3e58MMJkLZSu03WhZc7ZojG+OpMHUhTY4R5u7+krM=; b=NtT0v082bYJzr0LRGWS2OBOTQh8cJJrwf4GqZc84/QCmvkXOklqvetI+/x/S17qXVq 5o0W3bZQggccP3EkMQemTk18oy6zwC+SsBzI86/HH+1nzjb4/cUnmj5jxxSjofejNc5d 0JxM6PKez8L4CWd3Su2mMWu+FT5op99gLc6jzERP2lR/Y9IbMJVFsotK74chKUATueo5 k2Rj7DfCFjBpNYQsg3xup7NhH2Tr1Zs1ok65A4/VJx6iccXF/ooduZAYtWFkJPnyTd/b ekmssXsALdMKX6BkVHi2/gMOjlKO3iH/IppTX93+8u0FwDpxfTG1BySIv9eYg01b8fnU /VXg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id r6si3690391pgv.358.2021.10.09.10.22.20; Sat, 09 Oct 2021 10:22:32 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232123AbhJIRWV (ORCPT + 99 others); Sat, 9 Oct 2021 13:22:21 -0400 Received: from relay5-d.mail.gandi.net ([217.70.183.197]:48333 "EHLO relay5-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229928AbhJIRWU (ORCPT ); Sat, 9 Oct 2021 13:22:20 -0400 Received: (Authenticated sender: alex@ghiti.fr) by relay5-d.mail.gandi.net (Postfix) with ESMTPSA id 938581C0002; Sat, 9 Oct 2021 17:20:20 +0000 (UTC) Subject: Re: [PATCH v7 1/3] riscv: Introduce CONFIG_RELOCATABLE To: Alexandre Ghiti , Michael Ellerman , Benjamin Herrenschmidt , Paul Mackerras , Paul Walmsley , Palmer Dabbelt , Albert Ou , linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org References: <20211009171259.2515351-1-alexandre.ghiti@canonical.com> <20211009171259.2515351-2-alexandre.ghiti@canonical.com> From: Alexandre ghiti Message-ID: Date: Sat, 9 Oct 2021 19:20:20 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0 MIME-Version: 1.0 In-Reply-To: <20211009171259.2515351-2-alexandre.ghiti@canonical.com> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Content-Language: en-US Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Arf, I have sent this patchset with the wrong email address. @Palmer tell me if you want me to resend it correctly. Thanks, Alex On 10/9/21 7:12 PM, Alexandre Ghiti wrote: > From: Alexandre Ghiti > > This config allows to compile 64b kernel as PIE and to relocate it at > any virtual address at runtime: this paves the way to KASLR. > Runtime relocation is possible since relocation metadata are embedded into > the kernel. > > Note that relocating at runtime introduces an overhead even if the > kernel is loaded at the same address it was linked at and that the compiler > options are those used in arm64 which uses the same RELA relocation > format. > > Signed-off-by: Alexandre Ghiti > --- > arch/riscv/Kconfig | 12 ++++++++ > arch/riscv/Makefile | 7 +++-- > arch/riscv/kernel/vmlinux.lds.S | 6 ++++ > arch/riscv/mm/Makefile | 4 +++ > arch/riscv/mm/init.c | 54 ++++++++++++++++++++++++++++++++- > 5 files changed, 80 insertions(+), 3 deletions(-) > > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig > index ea16fa2dd768..043ba92559fa 100644 > --- a/arch/riscv/Kconfig > +++ b/arch/riscv/Kconfig > @@ -213,6 +213,18 @@ config PGTABLE_LEVELS > config LOCKDEP_SUPPORT > def_bool y > > +config RELOCATABLE > + bool > + depends on MMU && 64BIT && !XIP_KERNEL > + help > + This builds a kernel as a Position Independent Executable (PIE), > + which retains all relocation metadata required to relocate the > + kernel binary at runtime to a different virtual address than the > + address it was linked at. > + Since RISCV uses the RELA relocation format, this requires a > + relocation pass at runtime even if the kernel is loaded at the > + same address it was linked at. > + > source "arch/riscv/Kconfig.socs" > source "arch/riscv/Kconfig.erratas" > > diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile > index 0eb4568fbd29..2f509915f246 100644 > --- a/arch/riscv/Makefile > +++ b/arch/riscv/Makefile > @@ -9,9 +9,12 @@ > # > > OBJCOPYFLAGS := -O binary > -LDFLAGS_vmlinux := > +ifeq ($(CONFIG_RELOCATABLE),y) > + LDFLAGS_vmlinux += -shared -Bsymbolic -z notext -z norelro > + KBUILD_CFLAGS += -fPIE > +endif > ifeq ($(CONFIG_DYNAMIC_FTRACE),y) > - LDFLAGS_vmlinux := --no-relax > + LDFLAGS_vmlinux += --no-relax > KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY > CC_FLAGS_FTRACE := -fpatchable-function-entry=8 > endif > diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S > index 5104f3a871e3..862a8c09723c 100644 > --- a/arch/riscv/kernel/vmlinux.lds.S > +++ b/arch/riscv/kernel/vmlinux.lds.S > @@ -133,6 +133,12 @@ SECTIONS > > BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0) > > + .rela.dyn : ALIGN(8) { > + __rela_dyn_start = .; > + *(.rela .rela*) > + __rela_dyn_end = .; > + } > + > #ifdef CONFIG_EFI > . = ALIGN(PECOFF_SECTION_ALIGNMENT); > __pecoff_data_virt_size = ABSOLUTE(. - __pecoff_text_end); > diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile > index 7ebaef10ea1b..2d33ec574bbb 100644 > --- a/arch/riscv/mm/Makefile > +++ b/arch/riscv/mm/Makefile > @@ -1,6 +1,10 @@ > # SPDX-License-Identifier: GPL-2.0-only > > CFLAGS_init.o := -mcmodel=medany > +ifdef CONFIG_RELOCATABLE > +CFLAGS_init.o += -fno-pie > +endif > + > ifdef CONFIG_FTRACE > CFLAGS_REMOVE_init.o = $(CC_FLAGS_FTRACE) > CFLAGS_REMOVE_cacheflush.o = $(CC_FLAGS_FTRACE) > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c > index c0cddf0fc22d..42041c12d496 100644 > --- a/arch/riscv/mm/init.c > +++ b/arch/riscv/mm/init.c > @@ -20,6 +20,9 @@ > #include > #include > #include > +#ifdef CONFIG_RELOCATABLE > +#include > +#endif > > #include > #include > @@ -103,7 +106,7 @@ static void __init print_vm_layout(void) > print_mlm("lowmem", (unsigned long)PAGE_OFFSET, > (unsigned long)high_memory); > #ifdef CONFIG_64BIT > - print_mlm("kernel", (unsigned long)KERNEL_LINK_ADDR, > + print_mlm("kernel", (unsigned long)kernel_map.virt_addr, > (unsigned long)ADDRESS_SPACE_END); > #endif > } > @@ -518,6 +521,44 @@ static __init pgprot_t pgprot_from_va(uintptr_t va) > #error "setup_vm() is called from head.S before relocate so it should not use absolute addressing." > #endif > > +#ifdef CONFIG_RELOCATABLE > +extern unsigned long __rela_dyn_start, __rela_dyn_end; > + > +static void __init relocate_kernel(void) > +{ > + Elf64_Rela *rela = (Elf64_Rela *)&__rela_dyn_start; > + /* > + * This holds the offset between the linked virtual address and the > + * relocated virtual address. > + */ > + uintptr_t reloc_offset = kernel_map.virt_addr - KERNEL_LINK_ADDR; > + /* > + * This holds the offset between kernel linked virtual address and > + * physical address. > + */ > + uintptr_t va_kernel_link_pa_offset = KERNEL_LINK_ADDR - kernel_map.phys_addr; > + > + for ( ; rela < (Elf64_Rela *)&__rela_dyn_end; rela++) { > + Elf64_Addr addr = (rela->r_offset - va_kernel_link_pa_offset); > + Elf64_Addr relocated_addr = rela->r_addend; > + > + if (rela->r_info != R_RISCV_RELATIVE) > + continue; > + > + /* > + * Make sure to not relocate vdso symbols like rt_sigreturn > + * which are linked from the address 0 in vmlinux since > + * vdso symbol addresses are actually used as an offset from > + * mm->context.vdso in VDSO_OFFSET macro. > + */ > + if (relocated_addr >= KERNEL_LINK_ADDR) > + relocated_addr += reloc_offset; > + > + *(Elf64_Addr *)addr = relocated_addr; > + } > +} > +#endif /* CONFIG_RELOCATABLE */ > + > #ifdef CONFIG_XIP_KERNEL > static void __init create_kernel_page_table(pgd_t *pgdir, > __always_unused bool early) > @@ -625,6 +666,17 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) > BUG_ON((kernel_map.virt_addr + kernel_map.size) > ADDRESS_SPACE_END - SZ_4K); > #endif > > +#ifdef CONFIG_RELOCATABLE > + /* > + * Early page table uses only one PGDIR, which makes it possible > + * to map PGDIR_SIZE aligned on PGDIR_SIZE: if the relocation offset > + * makes the kernel cross over a PGDIR_SIZE boundary, raise a bug > + * since a part of the kernel would not get mapped. > + */ > + BUG_ON(PGDIR_SIZE - (kernel_map.virt_addr & (PGDIR_SIZE - 1)) < kernel_map.size); > + relocate_kernel(); > +#endif > + > pt_ops.alloc_pte = alloc_pte_early; > pt_ops.get_pte_virt = get_pte_virt_early; > #ifndef __PAGETABLE_PMD_FOLDED