From nobody Thu Feb 12 04:51:46 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 01262C77B60 for ; Fri, 28 Apr 2023 09:57:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346043AbjD1J5i (ORCPT ); Fri, 28 Apr 2023 05:57:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36920 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346033AbjD1J5U (ORCPT ); Fri, 28 Apr 2023 05:57:20 -0400 Received: from out187-21.us.a.mail.aliyun.com (out187-21.us.a.mail.aliyun.com [47.90.187.21]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2F7ED5BA0 for ; Fri, 28 Apr 2023 02:56:19 -0700 (PDT) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R151e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018047187;MF=houwenlong.hwl@antgroup.com;NM=1;PH=DS;RN=13;SR=0;TI=SMTPD_---.STFoGX6_1682675596; Received: from localhost(mailfrom:houwenlong.hwl@antgroup.com fp:SMTPD_---.STFoGX6_1682675596) by smtp.aliyun-inc.com; Fri, 28 Apr 2023 17:53:17 +0800 From: "Hou Wenlong" To: linux-kernel@vger.kernel.org Cc: "Thomas Garnier" , "Lai Jiangshan" , "Kees Cook" , "Hou Wenlong" , "Thomas Gleixner" , "Ingo Molnar" , "Borislav Petkov" , "Dave Hansen" , , "H. Peter Anvin" , "Sami Tolvanen" , "=?UTF-8?B?UGV0ZXIgWmlqbHN0cmEgKEludGVsKQ==?=" Subject: [PATCH RFC 27/43] x86/relocs: Handle PIE relocations Date: Fri, 28 Apr 2023 17:51:07 +0800 Message-Id: X-Mailer: git-send-email 2.31.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" From: Thomas Garnier From: Thomas Garnier Change the relocation tool to correctly handle relocations generated by -fPIE option: - Add relocation for each entry of the .got section given the linker does not generate R_X86_64_GLOB_DAT on a simple link. - Ignore R_X86_64_GOTPCREL. Signed-off-by: Thomas Garnier Signed-off-by: Hou Wenlong Cc: Lai Jiangshan Cc: Kees Cook --- arch/x86/tools/relocs.c | 96 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index 038e9c12fad3..97ac96195232 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c @@ -42,6 +42,7 @@ struct section { Elf32_Word *xsymtab; Elf_Rel *reltab; char *strtab; + Elf_Addr *got; }; static struct section *secs; =20 @@ -308,6 +309,36 @@ static Elf_Sym *sym_lookup(const char *symname) return 0; } =20 +static Elf_Sym *sym_lookup_addr(Elf_Addr addr, const char **name) +{ + int i; + + for (i =3D 0; i < ehdr.e_shnum; i++) { + struct section *sec =3D &secs[i]; + long nsyms; + Elf_Sym *symtab; + Elf_Sym *sym; + + if (sec->shdr.sh_type !=3D SHT_SYMTAB) + continue; + + nsyms =3D sec->shdr.sh_size/sizeof(Elf_Sym); + symtab =3D sec->symtab; + + for (sym =3D symtab; --nsyms >=3D 0; sym++) { + if (sym->st_value =3D=3D addr) { + if (name) { + *name =3D sym_name(sec->link->strtab, + sym); + } + return sym; + } + } + } + return 0; +} + + #if BYTE_ORDER =3D=3D LITTLE_ENDIAN #define le16_to_cpu(val) (val) #define le32_to_cpu(val) (val) @@ -588,6 +619,35 @@ static void read_relocs(FILE *fp) } } =20 +static void read_got(FILE *fp) +{ + int i; + + for (i =3D 0; i < ehdr.e_shnum; i++) { + struct section *sec =3D &secs[i]; + + sec->got =3D NULL; + if (sec->shdr.sh_type !=3D SHT_PROGBITS || + strcmp(sec_name(i), ".got")) { + continue; + } + sec->got =3D malloc(sec->shdr.sh_size); + if (!sec->got) { + die("malloc of %" FMT " bytes for got failed\n", + sec->shdr.sh_size); + } + if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { + die("Seek to %" FMT " failed: %s\n", + sec->shdr.sh_offset, strerror(errno)); + } + if (fread(sec->got, 1, sec->shdr.sh_size, fp) + !=3D sec->shdr.sh_size) { + die("Cannot read got: %s\n", + strerror(errno)); + } + } +} + =20 static void print_absolute_symbols(void) { @@ -718,6 +778,32 @@ static void add_reloc(struct relocs *r, uint32_t offse= t) r->offset[r->count++] =3D offset; } =20 +/* + * The linker does not generate relocations for the GOT for the kernel. + * If a GOT is found, simulate the relocations that should have been inclu= ded. + */ +static void walk_got_table(int (*process)(struct section *sec, Elf_Rel *re= l, + Elf_Sym *sym, const char *symname), + struct section *sec) +{ + int i; + Elf_Addr entry; + Elf_Sym *sym; + const char *symname; + Elf_Rel rel; + + for (i =3D 0; i < sec->shdr.sh_size/sizeof(Elf_Addr); i++) { + entry =3D sec->got[i]; + sym =3D sym_lookup_addr(entry, &symname); + if (!sym) + die("Could not found got symbol for entry %d\n", i); + rel.r_offset =3D sec->shdr.sh_addr + i * sizeof(Elf_Addr); + rel.r_info =3D ELF_BITS =3D=3D 64 ? R_X86_64_GLOB_DAT + : R_386_GLOB_DAT; + process(sec, &rel, sym, symname); + } +} + static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, const char *symname)) { @@ -731,6 +817,8 @@ static void walk_relocs(int (*process)(struct section *= sec, Elf_Rel *rel, struct section *sec =3D &secs[i]; =20 if (sec->shdr.sh_type !=3D SHT_REL_TYPE) { + if (sec->got) + walk_got_table(process, sec); continue; } sec_symtab =3D sec->link; @@ -842,6 +930,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel= , ElfW(Sym) *sym, offset +=3D per_cpu_load_addr; =20 switch (r_type) { + case R_X86_64_GOTPCREL: case R_X86_64_NONE: /* NONE can be ignored. */ break; @@ -905,7 +994,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel= , ElfW(Sym) *sym, * the relocations are processed. * Make sure that the offset will fit. */ - if ((int32_t)offset !=3D (int64_t)offset) + if (r_type !=3D R_X86_64_64 && (int32_t)offset !=3D (int64_t)offset) die("Relocation offset doesn't fit in 32 bits\n"); =20 if (r_type =3D=3D R_X86_64_64) @@ -914,6 +1003,10 @@ static int do_reloc64(struct section *sec, Elf_Rel *r= el, ElfW(Sym) *sym, add_reloc(&relocs32, offset); break; =20 + case R_X86_64_GLOB_DAT: + add_reloc(&relocs64, offset); + break; + default: die("Unsupported relocation type: %s (%d)\n", rel_type(r_type), r_type); @@ -1188,6 +1281,7 @@ void process(FILE *fp, int use_real_mode, int as_text, read_strtabs(fp); read_symtabs(fp); read_relocs(fp); + read_got(fp); if (ELF_BITS =3D=3D 64) percpu_init(); if (show_absolute_syms) { --=20 2.31.1