From patchwork Thu Jan 14 21:47:05 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: 8035801 Return-Path: X-Original-To: patchwork-xen-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id D8DC9BEEE5 for ; Thu, 14 Jan 2016 21:50:32 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C66A220390 for ; Thu, 14 Jan 2016 21:50:31 +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 4CDA420357 for ; Thu, 14 Jan 2016 21:50:29 +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 1aJpjv-0006UF-4C; Thu, 14 Jan 2016 21:47:31 +0000 Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aJpjt-0006Ri-52 for xen-devel@lists.xenproject.org; Thu, 14 Jan 2016 21:47:29 +0000 Received: from [193.109.254.147] by server-8.bemta-14.messagelabs.com id 6E/F4-24450-07718965; Thu, 14 Jan 2016 21:47:28 +0000 X-Env-Sender: konrad@char.us.oracle.com X-Msg-Ref: server-4.tower-27.messagelabs.com!1452808045!16023507!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 63700 invoked from network); 14 Jan 2016 21:47:27 -0000 Received: from userp1040.oracle.com (HELO userp1040.oracle.com) (156.151.31.81) by server-4.tower-27.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 14 Jan 2016 21:47:27 -0000 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u0ELlKOo021446 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Thu, 14 Jan 2016 21:47:20 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u0ELlKtH023562 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Thu, 14 Jan 2016 21:47:20 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u0ELlJMg004953; Thu, 14 Jan 2016 21:47:19 GMT Received: from char.us.oracle.com (/10.137.176.158) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 14 Jan 2016 13:47:19 -0800 Received: by char.us.oracle.com (Postfix, from userid 1000) id 5D5286A4DAE; Thu, 14 Jan 2016 16:47:17 -0500 (EST) From: Konrad Rzeszutek Wilk To: xen-devel@lists.xenproject.org, ross.lagerwall@citrix.com, mpohlack@amazon.com, andrew.cooper3@citrix.com, stefano.stabellini@citrix.com, jbeulich@suse.com, ian.jackson@eu.citrix.com, ian.campbell@citrix.com, wei.liu2@citrix.com, sasha.levin@oracle.com Date: Thu, 14 Jan 2016 16:47:05 -0500 Message-Id: <1452808031-706-8-git-send-email-konrad.wilk@oracle.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1452808031-706-1-git-send-email-konrad.wilk@oracle.com> References: <1452808031-706-1-git-send-email-konrad.wilk@oracle.com> X-Source-IP: userv0021.oracle.com [156.151.31.71] Cc: Konrad Rzeszutek Wilk Subject: [Xen-devel] [PATCH v2 07/13] xsplice: Add helper elf routines (v2) 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. 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. - Add checks for ELF file. - Add name to be printed. - Add len for easier ELF checks. - Expand on the checks. Add macro. --- xen/common/Makefile | 1 + xen/common/xsplice_elf.c | 201 ++++++++++++++++++++++++++++++++++++++++++ xen/include/xen/xsplice_elf.h | 37 ++++++++ 3 files changed, 239 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 6fdeccf..0c9d527 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -73,3 +73,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..a5e9d63 --- /dev/null +++ b/xen/common/xsplice_elf.c @@ -0,0 +1,201 @@ +#include +#include +#include +#include + +#define return_(x) { printk(XENLOG_DEBUG "%s:%d rc: %d\n", \ + __func__,__LINE__, x); return x; } + +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..60c932b --- /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 char 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__ */