Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp750008ybz; Wed, 15 Apr 2020 18:08:06 -0700 (PDT) X-Google-Smtp-Source: APiQypK6SVWfLPU2JOOjJEr11bRHqTSYhoQ7vu5ZH7/eBszsVK+ld+xEqVm5vUVeTQdkDcPoAmmr X-Received: by 2002:a17:906:3713:: with SMTP id d19mr7175084ejc.111.1586999286165; Wed, 15 Apr 2020 18:08:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1586999286; cv=none; d=google.com; s=arc-20160816; b=iCra7SgM+0bjTc1oKBAnSVLZxA0zJkM+EIlaVVdaIMY+/Zb23n/CMFAi5Tasyo9AR3 oJJy4a1aLqb+kR16+QbXfzNXjwX9Y32mCMgB5wsy4dYnsRWz98upyyEyDMgQ8hSCpej/ l77pUUwGf6uGRFZuYHDN24URt0MYYbZ3QR9yA145vEgkhN44YosM7Wg2FLdzSUq9MwQ1 gNNOwyJd+rQWmKo+4MyOy7x8Up6gjUTS/B4gPiIwE+8DVAT4Xgb+BLi4l9jsrQu/DDDC nn3qISetTUvuuV51PqA0Ly7npeGpV+sx0L8GPtfNJjo8I/E4KBZCn2pwOWQxMh5BsFe4 NdkQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :ironport-sdr:ironport-sdr; bh=OApK0wHtaBlFfS+NEHJfKXl7YazHZI+xjgqmlHujVsI=; b=QHrR96qHXTMHSToGkdLqQ2Ebs0vpNpGXWe/mB4mppplY/PwNpMy0bQSFTxraQbK3/Q zN4urvqMwE/4FmHoFepAX4snXRz5Qjadc7+vLIYiY/VxbbiDoXoIRfjvnhze25iXlaYX boxUQsm0QuuE6/9SHzKSTGA39wMAFlUT3wiRAl3qZ19Nb6Qy2LmNVlYX/qWbjBepHOsV Y/scBGoTl8KFyVAr8CRNuPF0C2Qy61zauq//pPRC4Nb4XAg6OHHi0cmUhj0h8YM9eJev TzrY6geUXuHDsXJgH7gKaNK6d0FGSHDnFNALKzn9n39HL722fpdM42Sgo8aUJ9XmoASa JyFg== 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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id l9si11587913eds.19.2020.04.15.18.07.41; Wed, 15 Apr 2020 18:08:06 -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; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2442245AbgDOVF5 (ORCPT + 99 others); Wed, 15 Apr 2020 17:05:57 -0400 Received: from mga09.intel.com ([134.134.136.24]:27162 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2442216AbgDOVFM (ORCPT ); Wed, 15 Apr 2020 17:05:12 -0400 IronPort-SDR: ftW4g7ADyfb0Jk4TCbhFd3/q6AF7bdiVJ4n66qit9mrF2uV7xIV+aMDTwd0qbHAu4Yln+wsYFP ZNvRp7AGVo8g== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Apr 2020 14:05:11 -0700 IronPort-SDR: UpFeYLiKRyp2RNd5vkLAbnL/v4lIMZ1duGfVozOurb+gkL7CBSo9BisVHyZ6FnoidQnyZMSB+3 EjHio4fjuNMg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,388,1580803200"; d="scan'208";a="455035513" Received: from kcaccard-mobl.amr.corp.intel.com (HELO kcaccard-mobl1.jf.intel.com) ([10.209.116.191]) by fmsmga006.fm.intel.com with ESMTP; 15 Apr 2020 14:05:08 -0700 From: Kristen Carlson Accardi To: keescook@chromium.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, x86@kernel.org Cc: arjan@linux.intel.com, linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com, rick.p.edgecomb@intel.com Subject: [PATCH 2/9] x86: tools/relocs: Support >64K section headers Date: Wed, 15 Apr 2020 14:04:44 -0700 Message-Id: <20200415210452.27436-3-kristen@linux.intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200415210452.27436-1-kristen@linux.intel.com> References: <20200415210452.27436-1-kristen@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org While it is already supported to find the total number of section headers if we exceed 64K sections, we need to support the extended symbol table to get section header indexes for symbols when there are > 64K sections. Parse the elf file to read the extended symbol table info, and then replace all direct references to st_shndx with calls to sym_index(), which will determine whether we can read the value directly or whether we need to pull it out of the extended table. Signed-off-by: Kristen Carlson Accardi Reviewed-by: Kees Cook --- arch/x86/tools/relocs.c | 104 ++++++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 26 deletions(-) diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index ce7188cbdae5..a00dc133f109 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c @@ -14,6 +14,10 @@ static Elf_Ehdr ehdr; static unsigned long shnum; static unsigned int shstrndx; +static unsigned int shsymtabndx; +static unsigned int shxsymtabndx; + +static int sym_index(Elf_Sym *sym); struct relocs { uint32_t *offset; @@ -32,6 +36,7 @@ struct section { Elf_Shdr shdr; struct section *link; Elf_Sym *symtab; + Elf32_Word *xsymtab; Elf_Rel *reltab; char *strtab; }; @@ -265,7 +270,7 @@ static const char *sym_name(const char *sym_strtab, Elf_Sym *sym) name = sym_strtab + sym->st_name; } else { - name = sec_name(sym->st_shndx); + name = sec_name(sym_index(sym)); } return name; } @@ -335,6 +340,23 @@ static uint64_t elf64_to_cpu(uint64_t val) #define elf_xword_to_cpu(x) elf32_to_cpu(x) #endif +static int sym_index(Elf_Sym *sym) +{ + Elf_Sym *symtab = secs[shsymtabndx].symtab; + Elf32_Word *xsymtab = secs[shxsymtabndx].xsymtab; + unsigned long offset; + int index; + + if (sym->st_shndx != SHN_XINDEX) + return sym->st_shndx; + + /* calculate offset of sym from head of table. */ + offset = (unsigned long) sym - (unsigned long) symtab; + index = offset/sizeof(*sym); + + return elf32_to_cpu(xsymtab[index]); +} + static void read_ehdr(FILE *fp) { if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) { @@ -468,31 +490,60 @@ static void read_strtabs(FILE *fp) static void read_symtabs(FILE *fp) { int i,j; + for (i = 0; i < shnum; i++) { struct section *sec = &secs[i]; - if (sec->shdr.sh_type != SHT_SYMTAB) { + int num_syms; + + switch (sec->shdr.sh_type) { + case SHT_SYMTAB_SHNDX: + sec->xsymtab = malloc(sec->shdr.sh_size); + if (!sec->xsymtab) { + die("malloc of %d bytes for xsymtab failed\n", + sec->shdr.sh_size); + } + if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { + die("Seek to %d failed: %s\n", + sec->shdr.sh_offset, strerror(errno)); + } + if (fread(sec->xsymtab, 1, sec->shdr.sh_size, fp) + != sec->shdr.sh_size) { + die("Cannot read extended symbol table: %s\n", + strerror(errno)); + } + shxsymtabndx = i; + continue; + + case SHT_SYMTAB: + num_syms = sec->shdr.sh_size/sizeof(Elf_Sym); + + sec->symtab = malloc(sec->shdr.sh_size); + if (!sec->symtab) { + die("malloc of %d bytes for symtab failed\n", + sec->shdr.sh_size); + } + if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { + die("Seek to %d failed: %s\n", + sec->shdr.sh_offset, strerror(errno)); + } + if (fread(sec->symtab, 1, sec->shdr.sh_size, fp) + != sec->shdr.sh_size) { + die("Cannot read symbol table: %s\n", + strerror(errno)); + } + for (j = 0; j < num_syms; j++) { + Elf_Sym *sym = &sec->symtab[j]; + + sym->st_name = elf_word_to_cpu(sym->st_name); + sym->st_value = elf_addr_to_cpu(sym->st_value); + sym->st_size = elf_xword_to_cpu(sym->st_size); + sym->st_shndx = elf_half_to_cpu(sym->st_shndx); + } + shsymtabndx = i; + continue; + + default: continue; - } - sec->symtab = malloc(sec->shdr.sh_size); - if (!sec->symtab) { - die("malloc of %d bytes for symtab failed\n", - sec->shdr.sh_size); - } - if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { - die("Seek to %d failed: %s\n", - sec->shdr.sh_offset, strerror(errno)); - } - if (fread(sec->symtab, 1, sec->shdr.sh_size, fp) - != sec->shdr.sh_size) { - die("Cannot read symbol table: %s\n", - strerror(errno)); - } - for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Sym); j++) { - Elf_Sym *sym = &sec->symtab[j]; - sym->st_name = elf_word_to_cpu(sym->st_name); - sym->st_value = elf_addr_to_cpu(sym->st_value); - sym->st_size = elf_xword_to_cpu(sym->st_size); - sym->st_shndx = elf_half_to_cpu(sym->st_shndx); } } } @@ -759,13 +810,14 @@ static void percpu_init(void) */ static int is_percpu_sym(ElfW(Sym) *sym, const char *symname) { - return (sym->st_shndx == per_cpu_shndx) && + int shndx = sym_index(sym); + + return (shndx == per_cpu_shndx) && strcmp(symname, "__init_begin") && strcmp(symname, "__per_cpu_load") && strncmp(symname, "init_per_cpu_", 13); } - static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, const char *symname) { @@ -1088,7 +1140,7 @@ static int do_reloc_info(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, sec_name(sec->shdr.sh_info), rel_type(ELF_R_TYPE(rel->r_info)), symname, - sec_name(sym->st_shndx)); + sec_name(sym_index(sym))); return 0; } -- 2.20.1