From patchwork Fri Feb 12 18:05:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konrad Rzeszutek Wilk X-Patchwork-Id: 8294991 Return-Path: X-Original-To: patchwork-xen-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 1889D9F1E0 for ; Fri, 12 Feb 2016 18:09:41 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B9C9E20430 for ; Fri, 12 Feb 2016 18:09:38 +0000 (UTC) Received: from lists.xen.org (lists.xenproject.org [50.57.142.19]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id C18B920437 for ; Fri, 12 Feb 2016 18:09:35 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aUI7Q-00068g-Am; Fri, 12 Feb 2016 18:07:00 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aUI7J-00063I-Ee for xen-devel@lists.xen.org; Fri, 12 Feb 2016 18:06:53 +0000 Received: from [85.158.137.68] by server-1.bemta-3.messagelabs.com id 6D/73-02745-C3F1EB65; Fri, 12 Feb 2016 18:06:52 +0000 X-Env-Sender: konrad@char.us.oracle.com X-Msg-Ref: server-10.tower-31.messagelabs.com!1455300410!22045567!1 X-Originating-IP: [156.151.31.81] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogMTU2LjE1MS4zMS44MSA9PiAyODgzMzk=\n X-StarScan-Received: X-StarScan-Version: 7.35.1; banners=-,-,- X-VirusChecked: Checked Received: (qmail 22195 invoked from network); 12 Feb 2016 18:06:51 -0000 Received: from userp1040.oracle.com (HELO userp1040.oracle.com) (156.151.31.81) by server-10.tower-31.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 12 Feb 2016 18:06:51 -0000 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u1CI6gdX004455 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 12 Feb 2016 18:06:43 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u1CI6g9P005997 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Fri, 12 Feb 2016 18:06:42 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u1CI6gTf025690; Fri, 12 Feb 2016 18:06:42 GMT Received: from char.us.oracle.com (/10.137.176.158) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 12 Feb 2016 10:06:41 -0800 Received: by char.us.oracle.com (Postfix, from userid 1000) id 981A46A4BF5; Fri, 12 Feb 2016 13:06:39 -0500 (EST) From: Konrad Rzeszutek Wilk To: xen-devel@lists.xenproject.org, andrew.cooper3@citrix.com, konrad@kernel.org, mpohlack@amazon.de, ross.lagerwall@citrix.com, sasha.levin@citrix.com, jinsong.liu@alibaba-inc.com, Ian Campbell , Ian Jackson , Jan Beulich , Keir Fraser , Tim Deegan , xen-devel@lists.xen.org Date: Fri, 12 Feb 2016 13:05:43 -0500 Message-Id: <1455300361-13092-6-git-send-email-konrad.wilk@oracle.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1455300361-13092-1-git-send-email-konrad.wilk@oracle.com> References: <1455300361-13092-1-git-send-email-konrad.wilk@oracle.com> X-Source-IP: userv0022.oracle.com [156.151.31.74] Cc: Konrad Rzeszutek Wilk Subject: [Xen-devel] [PATCH v3 05/23] xsplice: Add helper elf routines (v4) X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Ross Lagerwall Add Elf routines and data structures in preparation for loading an xSplice payload. We also add an macro that will print where we failed during the ELF parsing - which is only available during debug builds. In production (debug=n) we only return the error value. Signed-off-by: Ross Lagerwall Signed-off-by: Konrad Rzeszutek Wilk --- v2: - With the #define ELFSIZE in the ARM file we can use the common #defines instead of using #ifdef CONFIG_ARM_32. Moved to another patch. - Add checks for ELF file. - Add name to be printed. - Add len for easier ELF checks. - Expand on the checks. Add macro. v3: Remove the return_ macro v4: Add return_ macro back but make it depend on debug=y --- xen/common/Makefile | 1 + xen/common/xsplice_elf.c | 205 ++++++++++++++++++++++++++++++++++++++++++ xen/include/xen/xsplice_elf.h | 37 ++++++++ 3 files changed, 243 insertions(+) create mode 100644 xen/common/xsplice_elf.c create mode 100644 xen/include/xen/xsplice_elf.h diff --git a/xen/common/Makefile b/xen/common/Makefile index 43b3911..a8ceaff 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -74,3 +74,4 @@ subdir-y += libelf subdir-$(CONFIG_HAS_DEVICE_TREE) += libfdt obj-$(CONFIG_XSPLICE) += xsplice.o +obj-$(CONFIG_XSPLICE) += xsplice_elf.o diff --git a/xen/common/xsplice_elf.c b/xen/common/xsplice_elf.c new file mode 100644 index 0000000..d9f9002 --- /dev/null +++ b/xen/common/xsplice_elf.c @@ -0,0 +1,205 @@ +#include +#include +#include +#include + +#ifdef NDEBUG +#define return_(x) return x +#else +#define return_(x) { printk(XENLOG_DEBUG "%s:%d rc: %d\n", \ + __func__,__LINE__, x); return x; } +#endif + +struct xsplice_elf_sec *xsplice_elf_sec_by_name(const struct xsplice_elf *elf, + const char *name) +{ + unsigned int i; + + for ( i = 0; i < elf->hdr->e_shnum; i++ ) + { + if ( !strcmp(name, elf->sec[i].name) ) + return &elf->sec[i]; + } + + return NULL; +} + +static int elf_resolve_sections(struct xsplice_elf *elf, uint8_t *data) +{ + struct xsplice_elf_sec *sec; + unsigned int i; + + sec = xmalloc_array(struct xsplice_elf_sec, elf->hdr->e_shnum); + if ( !sec ) + { + printk(XENLOG_ERR "Could not allocate memory for section table!\n"); + return_(-ENOMEM); + } + + /* N.B. We also will ingest SHN_UNDEF sections. */ + for ( i = 0; i < elf->hdr->e_shnum; i++ ) + { + ssize_t delta = elf->hdr->e_shoff + i * elf->hdr->e_shentsize; + + if ( delta + sizeof(Elf_Shdr) > elf->len ) + return_(-EINVAL); + + sec[i].sec = (Elf_Shdr *)(data + delta); + delta = sec[i].sec->sh_offset; + + if ( delta > elf->len ) + return_(-EINVAL); + + sec[i].data = data + delta; + /* Name is populated in xsplice_elf_sections_name. */ + sec[i].name = NULL; + + if ( sec[i].sec->sh_type == SHT_SYMTAB ) + { + if ( elf->symtab ) + return_(-EINVAL); + elf->symtab = &sec[i]; + /* elf->symtab->sec->sh_link would point to the right section + * but we hadn't finished parsing all the sections. */ + if ( elf->symtab->sec->sh_link > elf->hdr->e_shnum ) + return_(-EINVAL); + } + } + elf->sec = sec; + if ( !elf->symtab ) + return_(-EINVAL); + + /* There can be multiple SHT_STRTAB so pick the right one. */ + elf->strtab = &sec[elf->symtab->sec->sh_link]; + + if ( elf->symtab->sec->sh_size == 0 || elf->symtab->sec->sh_entsize == 0 ) + return_(-EINVAL); + + if ( elf->symtab->sec->sh_entsize != sizeof(Elf_Sym) ) + return_(-EINVAL); + + return 0; +} + +static int elf_resolve_section_names(struct xsplice_elf *elf, uint8_t *data) +{ + const char *shstrtab; + unsigned int i; + unsigned int offset, delta; + + /* The elf->sec[0 -> e_shnum] structures have been verified by elf_resolve_sections */ + /* Find file offset for section string table. */ + offset = elf->sec[elf->hdr->e_shstrndx].sec->sh_offset; + + if ( offset > elf->len ) + return_(-EINVAL); + + shstrtab = (const char *)(data + offset); + + /* We could ignore the first as it is reserved.. */ + for ( i = 0; i < elf->hdr->e_shnum; i++ ) + { + delta = elf->sec[i].sec->sh_name; + + if ( offset + delta > elf->len ) + return_(-EINVAL); + + elf->sec[i].name = shstrtab + delta; + } + return 0; +} + +static int elf_get_sym(struct xsplice_elf *elf, uint8_t *data) +{ + struct xsplice_elf_sec *symtab_sec, *strtab_sec; + struct xsplice_elf_sym *sym; + unsigned int i, delta, offset; + + symtab_sec = elf->symtab; + + strtab_sec = elf->strtab; + + /* Pointers arithmetic to get file offset. */ + offset = strtab_sec->data - data; + + ASSERT( offset == strtab_sec->sec->sh_offset ); + /* symtab_sec->data was computed in elf_resolve_sections. */ + ASSERT((symtab_sec->sec->sh_offset + data) == symtab_sec->data ); + + /* No need to check values as elf_resolve_sections did it. */ + elf->nsym = symtab_sec->sec->sh_size / symtab_sec->sec->sh_entsize; + + sym = xmalloc_array(struct xsplice_elf_sym, elf->nsym); + if ( !sym ) + { + printk(XENLOG_ERR "%s: Could not allocate memory for symbols\n", elf->name); + return_(-ENOMEM); + } + + for ( i = 0; i < elf->nsym; i++ ) + { + Elf_Sym *s; + + if ( i * sizeof(Elf_Sym) > elf->len ) + return_(-EINVAL); + + s = &((Elf_Sym *)symtab_sec->data)[i]; + + /* If st->name is STN_UNDEF it is zero, so the check will always be true. */ + delta = s->st_name; + /* Offset has been computed earlier. */ + if ( offset + delta > elf->len ) + return_(-EINVAL); + + sym[i].sym = s; + if ( s->st_name == STN_UNDEF ) + sym[i].name = NULL; + else + sym[i].name = (const char *)data + ( delta + offset ); + } + elf->sym = sym; + + return 0; +} + +int xsplice_elf_load(struct xsplice_elf *elf, uint8_t *data) +{ + int rc; + + elf->hdr = (Elf_Ehdr *)data; + + if ( sizeof(*elf->hdr) >= elf->len ) + return_(-EINVAL); + + if ( elf->hdr->e_shstrndx == SHN_UNDEF ) + return_(-EINVAL); + + /* Check that section name index is within the sections. */ + if ( elf->hdr->e_shstrndx > elf->hdr->e_shnum ) + return_(-EINVAL); + + rc = elf_resolve_sections(elf, data); + if ( rc ) + return rc; + + rc = elf_resolve_section_names(elf, data); + if ( rc ) + return rc; + + rc = elf_get_sym(elf, data); + if ( rc ) + return rc; + + return 0; +} + +void xsplice_elf_free(struct xsplice_elf *elf) +{ + xfree(elf->sec); + elf->sec = NULL; + xfree(elf->sym); + elf->sym = NULL; + elf->nsym = 0; + elf->name = NULL; + elf->len = 0; +} diff --git a/xen/include/xen/xsplice_elf.h b/xen/include/xen/xsplice_elf.h new file mode 100644 index 0000000..42dbc6f --- /dev/null +++ b/xen/include/xen/xsplice_elf.h @@ -0,0 +1,37 @@ +#ifndef __XEN_XSPLICE_ELF_H__ +#define __XEN_XSPLICE_ELF_H__ + +#include +#include + +/* The following describes an Elf file as consumed by xSplice. */ +struct xsplice_elf_sec { + Elf_Shdr *sec; /* Hooked up in elf_resolve_sections. */ + const char *name; /* Human readable name hooked in + elf_resolve_section_names. */ + const uint8_t *data; /* Pointer to the section (done by + elf_resolve_sections). */ +}; + +struct xsplice_elf_sym { + Elf_Sym *sym; + const char *name; +}; + +struct xsplice_elf { + const char *name; /* Pointer to payload->name. */ + ssize_t len; /* Length of the ELF file. */ + Elf_Ehdr *hdr; /* ELF file. */ + struct xsplice_elf_sec *sec; /* Array of sections, allocated by us. */ + struct xsplice_elf_sym *sym; /* Array of symbols , allocated by us. */ + unsigned int nsym; + struct xsplice_elf_sec *symtab;/* Pointer to .symtab section - aka to sec[x]. */ + struct xsplice_elf_sec *strtab;/* Pointer to .strtab section - aka to sec[y]. */ +}; + +struct xsplice_elf_sec *xsplice_elf_sec_by_name(const struct xsplice_elf *elf, + const char *name); +int xsplice_elf_load(struct xsplice_elf *elf, uint8_t *data); +void xsplice_elf_free(struct xsplice_elf *elf); + +#endif /* __XEN_XSPLICE_ELF_H__ */