| From f20692ec0cf00969a792bbc969e7ede057605e9b Mon Sep 17 00:00:00 2001 |
| From: Gerald Schaefer <gerald.schaefer@de.ibm.com> |
| Date: Mon, 21 Oct 2019 19:56:00 +0200 |
| Subject: [PATCH] s390/kaslr: add support for R_390_GLOB_DAT relocation type |
| |
| commit ac49303d9ef0ad98b79867a380ef23480e48870b upstream. |
| |
| Commit "bpf: Process in-kernel BTF" in linux-next introduced an undefined |
| __weak symbol, which results in an R_390_GLOB_DAT relocation type. That |
| is not yet handled by the KASLR relocation code, and the kernel stops with |
| the message "Unknown relocation type". |
| |
| Add code to detect and handle R_390_GLOB_DAT relocation types and undefined |
| symbols. |
| |
| Fixes: 805bc0bc238f ("s390/kernel: build a relocatable kernel") |
| Cc: <stable@vger.kernel.org> # v5.2+ |
| Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> |
| Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> |
| Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c |
| index 7b0d05414618..ceeacbeff600 100644 |
| --- a/arch/s390/boot/startup.c |
| +++ b/arch/s390/boot/startup.c |
| @@ -101,10 +101,18 @@ static void handle_relocs(unsigned long offset) |
| dynsym = (Elf64_Sym *) vmlinux.dynsym_start; |
| for (rela = rela_start; rela < rela_end; rela++) { |
| loc = rela->r_offset + offset; |
| - val = rela->r_addend + offset; |
| + val = rela->r_addend; |
| r_sym = ELF64_R_SYM(rela->r_info); |
| - if (r_sym) |
| - val += dynsym[r_sym].st_value; |
| + if (r_sym) { |
| + if (dynsym[r_sym].st_shndx != SHN_UNDEF) |
| + val += dynsym[r_sym].st_value + offset; |
| + } else { |
| + /* |
| + * 0 == undefined symbol table index (STN_UNDEF), |
| + * used for R_390_RELATIVE, only add KASLR offset |
| + */ |
| + val += offset; |
| + } |
| r_type = ELF64_R_TYPE(rela->r_info); |
| rc = arch_kexec_do_relocs(r_type, (void *) loc, val, 0); |
| if (rc) |
| diff --git a/arch/s390/kernel/machine_kexec_reloc.c b/arch/s390/kernel/machine_kexec_reloc.c |
| index 1dded39239f8..99e7951c199c 100644 |
| --- a/arch/s390/kernel/machine_kexec_reloc.c |
| +++ b/arch/s390/kernel/machine_kexec_reloc.c |
| @@ -26,6 +26,7 @@ int arch_kexec_do_relocs(int r_type, void *loc, unsigned long val, |
| *(u32 *)loc = val; |
| break; |
| case R_390_64: /* Direct 64 bit. */ |
| + case R_390_GLOB_DAT: |
| *(u64 *)loc = val; |
| break; |
| case R_390_PC16: /* PC relative 16 bit. */ |
| -- |
| 2.7.4 |
| |