Received: by 2002:a05:6902:102b:0:0:0:0 with SMTP id x11csp3776133ybt; Tue, 23 Jun 2020 10:25:27 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxJxZ6TXKBpIF8G31YZmJTolja/OrPUlys3xAaQQuPhWkz7Z/OukYLx0tYuK/PjU3lEz1jZ X-Received: by 2002:a17:906:685a:: with SMTP id a26mr12243890ejs.48.1592933126844; Tue, 23 Jun 2020 10:25:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1592933126; cv=none; d=google.com; s=arc-20160816; b=qGmcB1CgPOZhGxFR15zOxbUSk+meONEj5rd5nq4ncp4+5RPUxVl96Kmdk4xUFSsH2S w+Z8gg9fpdok7BJG+uEnd2Q20QNL0psOE13pAqlOUcgP2sTkDQZGmkVP9PKbDTBmjXJX tNI0ovVpnREKFehZeTLPBG6ztv3rM/h7pf/lp7gHJwpkMdzDjiq3iHws9oBrm3cx89kA BMibtVJ8zbaauKrMG7USO0fnzvbnp4aHIhsAKBg2c3RlPBB3wfVjsvdG1BD7m25hqlQP E3ioA636qqRax2F6efwEEadtuDxGVoderSAF2BQc8lPjYPBTP19MM/FgraHEtezZuIGg 6KDw== 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=Ab1gLPZ053IYB70xGfuq2orSir8R1BHkfcMagK6Lz+8=; b=hgjwY7E8vd/H0KpuOa6XoXIeel/djd/vJIaqrW0O78dtELR8JdraE2nGlITX2UKYsN XtoB2B0WkQX5fgQgB+TEn5Rs2KmlMLE5QfThsYPb5W1HPRGBJfXnSvvjYR5UQzOH4u39 M4CX9oNltnbWJzCaqurEKLHKCIUtloAZjabDH95wCRTJy3YHNrk6YrqBJYUmumuKtY7O ruurl5nRsLBvBB8Cw1XfjZg7wKbVDEB2inmIBN4G8CRIHTAcy7D+rHNW1TQPTQ6S3UuF KWg/XCvN8OqW617T1e1kVli/N9sj5RL7ynU3UojGH6MOxgP8XGk1S6GYLQc3Wn4HEYv9 fb9Q== 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 f12si4719165ejx.143.2020.06.23.10.24.40; Tue, 23 Jun 2020 10:25:26 -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 S1733069AbgFWRY2 (ORCPT + 99 others); Tue, 23 Jun 2020 13:24:28 -0400 Received: from mga11.intel.com ([192.55.52.93]:61940 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733038AbgFWRY0 (ORCPT ); Tue, 23 Jun 2020 13:24:26 -0400 IronPort-SDR: iQD6KxNLian68nt2N/N1D1ArqHE1dn8iiEO4kl3/jGbXbx8kmgiZ23M77H5UGVPD414sEzS78l LwHQT+pk6qaA== X-IronPort-AV: E=McAfee;i="6000,8403,9661"; a="142391466" X-IronPort-AV: E=Sophos;i="5.75,272,1589266800"; d="scan'208";a="142391466" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 23 Jun 2020 10:24:25 -0700 IronPort-SDR: Uuo+a3s0zik843KMbIpkl1mTqRXdI2LAqlBF4jFKJPVWc0k9dUSWoRy+dbSRfUyPPzp8JGLYqm OB+e/FBukDbA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,272,1589266800"; d="scan'208";a="423080034" Received: from kcaccard-mobl.amr.corp.intel.com (HELO kcaccard-mobl1.jf.intel.com) ([10.213.182.184]) by orsmga004.jf.intel.com with ESMTP; 23 Jun 2020 10:24:22 -0700 From: Kristen Carlson Accardi To: keescook@chromium.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, x86@kernel.org, "H. Peter Anvin" Cc: arjan@linux.intel.com, linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com, rick.p.edgecombe@intel.com, Kristen Carlson Accardi , Tony Luck Subject: [PATCH v3 02/10] x86: tools/relocs: Support >64K section headers Date: Tue, 23 Jun 2020 10:23:19 -0700 Message-Id: <20200623172327.5701-3-kristen@linux.intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200623172327.5701-1-kristen@linux.intel.com> References: <20200623172327.5701-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 the relocs tool already supports finding the total number of section headers if vmlinux exceeds 64K sections, it fails to read the extended symbol table to get section header indexes for symbols, causing incorrect symbol table indexes to be used when there are > 64K symbols. 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 the value can be read directly or whether the value should be pulled out of the extended table. Signed-off-by: Kristen Carlson Accardi Reviewed-by: Kees Cook Reviewed-by: Tony Luck Tested-by: Tony Luck --- 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..31b2d151aa63 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