From patchwork Fri Feb 12 18:05:57 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: 8295041 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 C2593C02AA for ; Fri, 12 Feb 2016 18:15:02 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7224B20421 for ; Fri, 12 Feb 2016 18:15:01 +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 F3CAB2042A for ; Fri, 12 Feb 2016 18:14:59 +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 1aUIDZ-0002nZ-KJ; Fri, 12 Feb 2016 18:13:21 +0000 Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aUIDX-0002nE-Ef for xen-devel@lists.xen.org; Fri, 12 Feb 2016 18:13:19 +0000 Received: from [193.109.254.147] by server-15.bemta-14.messagelabs.com id A5/F0-10115-04F1EB65; Fri, 12 Feb 2016 18:06:56 +0000 X-Env-Sender: konrad@char.us.oracle.com X-Msg-Ref: server-15.tower-27.messagelabs.com!1455300414!23440996!1 X-Originating-IP: [141.146.126.69] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogMTQxLjE0Ni4xMjYuNjkgPT4gMjc3MjE4\n X-StarScan-Received: X-StarScan-Version: 7.35.1; banners=-,-,- X-VirusChecked: Checked Received: (qmail 43440 invoked from network); 12 Feb 2016 18:06:55 -0000 Received: from aserp1040.oracle.com (HELO aserp1040.oracle.com) (141.146.126.69) by server-15.tower-27.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 12 Feb 2016 18:06:55 -0000 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u1CI6iBF025065 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 12 Feb 2016 18:06:44 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 u1CI6hNW014634 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Fri, 12 Feb 2016 18:06:43 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u1CI6hFm024677; Fri, 12 Feb 2016 18:06:43 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:43 -0800 Received: by char.us.oracle.com (Postfix, from userid 1000) id 224FC6A4BF3; Fri, 12 Feb 2016 13:06:41 -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, Keir Fraser , Jan Beulich , xen-devel@lists.xen.org Date: Fri, 12 Feb 2016 13:05:57 -0500 Message-Id: <1455300361-13092-20-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: userv0021.oracle.com [156.151.31.71] Cc: Konrad Rzeszutek Wilk Subject: [Xen-devel] [PATCH v3 19/23] xsplice, symbols: Implement symbol name resolution on address. (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 If in the payload we do not have the old_addr we can resolve the virtual address based on the UNDEFined symbols. Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Ross Lagerwall --- v1: Ross original version. v2: Include test-case and document update. --- docs/misc/xsplice.markdown | 1 - xen/arch/x86/Makefile | 6 +- xen/arch/x86/test/Makefile | 4 +- xen/arch/x86/test/xen_hello_world.c | 5 +- xen/common/symbols.c | 23 ++++++ xen/common/xsplice.c | 151 ++++++++++++++++++++++++++++++++++++ xen/common/xsplice_elf.c | 19 ++++- xen/include/xen/symbols.h | 2 + xen/include/xen/xsplice.h | 7 ++ 9 files changed, 208 insertions(+), 10 deletions(-) diff --git a/docs/misc/xsplice.markdown b/docs/misc/xsplice.markdown index c06cd9d..1a982f2 100644 --- a/docs/misc/xsplice.markdown +++ b/docs/misc/xsplice.markdown @@ -932,7 +932,6 @@ This is for further development of xSplice. The design must also have a mechanism for: - * Be able to lookup in the Xen hypervisor the symbol names of functions from the ELF payload. * Be able to patch .rodata, .bss, and .data sections. * Further safety checks (blacklist of which functions cannot be patched, check the stack, etc). diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 4a19ae9..5f7c57e 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -119,12 +119,14 @@ $(TARGET)-syms: prelink.o xen.lds $(BASEDIR)/common/symbols-dummy.o $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \ $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0 $(NM) -pa --format=sysv $(@D)/.$(@F).0 \ - | $(BASEDIR)/tools/symbols --sysv --sort >$(@D)/.$(@F).0.S + | $(BASEDIR)/tools/symbols --all-symbols --sysv --sort \ + >$(@D)/.$(@F).0.S $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0.o $(LD) $(LDFLAGS) -T xen.lds -N prelink.o \ $(@D)/.$(@F).0.o -o $(@D)/.$(@F).1 $(NM) -pa --format=sysv $(@D)/.$(@F).1 \ - | $(BASEDIR)/tools/symbols --sysv --sort --warn-dup >$(@D)/.$(@F).1.S + | $(BASEDIR)/tools/symbols --all-symbols --sysv --sort --warn-dup \ + >$(@D)/.$(@F).1.S $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1.o $(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id_linker) \ $(@D)/.$(@F).1.o -o $@ diff --git a/xen/arch/x86/test/Makefile b/xen/arch/x86/test/Makefile index de9693f..57c5189 100644 --- a/xen/arch/x86/test/Makefile +++ b/xen/arch/x86/test/Makefile @@ -32,14 +32,12 @@ clean:: # the last entry in the build target. # .PHONY: config.h -config.h: OLD_CODE=$(call CODE_ADDR,$(BASEDIR)/xen-syms,xen_extra_version) config.h: OLD_CODE_SZ=$(call CODE_SZ,$<,xen_hello_world) config.h: NEW_CODE_SZ=$(call CODE_SZ,$(BASEDIR)/xen-syms,xen_extra_version) config.h: xen_hello_world_func.o (set -e; \ echo "#define NEW_CODE_SZ $(NEW_CODE_SZ)"; \ - echo "#define OLD_CODE_SZ $(OLD_CODE_SZ)"; \ - echo "#define OLD_CODE $(OLD_CODE)") > $@ + echo "#define OLD_CODE_SZ $(OLD_CODE_SZ)") > $@ # # This target is only accessible if CONFIG_XSPLICE is defined, which diff --git a/xen/arch/x86/test/xen_hello_world.c b/xen/arch/x86/test/xen_hello_world.c index 6a1775b..6200fbe 100644 --- a/xen/arch/x86/test/xen_hello_world.c +++ b/xen/arch/x86/test/xen_hello_world.c @@ -6,10 +6,13 @@ static char name[] = "xen_hello_world"; extern const char *xen_hello_world(void); +/* External symbol. */ +extern const char *xen_extra_version(void); + struct xsplice_patch_func __section(".xsplice.funcs") xsplice_xen_hello_world = { .name = name, .new_addr = (unsigned long)(xen_hello_world), - .old_addr = OLD_CODE, + .old_addr = (unsigned long)(xen_extra_version), .new_size = NEW_CODE_SZ, .old_size = OLD_CODE_SZ, }; diff --git a/xen/common/symbols.c b/xen/common/symbols.c index bf5623f..406e5be 100644 --- a/xen/common/symbols.c +++ b/xen/common/symbols.c @@ -209,3 +209,26 @@ int xensyms_read(uint32_t *symnum, char *type, return 0; } + +uint64_t symbols_lookup_by_name(const char *symname) +{ + uint32_t symnum = 0; + uint64_t addr = 0, outaddr = 0; + int rc; + char type; + char name[KSYM_NAME_LEN + 1] = {0}; + + do { + rc = xensyms_read(&symnum, &type, &addr, name); + if ( rc ) + break; + + if ( !strcmp(name, symname) ) + { + outaddr = addr; + break; + } + } while ( name[0] != '\0' ); + + return outaddr; +} diff --git a/xen/common/xsplice.c b/xen/common/xsplice.c index 3f1da13..0b42a16 100644 --- a/xen/common/xsplice.c +++ b/xen/common/xsplice.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,9 @@ struct payload { #endif struct xsplice_build_id id; /* ELFNOTE_DESC(.note.gnu.build-id) of the payload. */ struct xsplice_build_id dep; /* ELFNOTE_DESC(.xsplice.depends). */ + struct xsplice_symbol *symtab; /* All symbols. */ + char *strtab; /* Pointer to .strtab. */ + unsigned int nsyms; /* Nr of entries in .strtab and symbols. */ char name[XEN_XSPLICE_NAME_SIZE + 1];/* Name of it. */ }; @@ -232,6 +236,8 @@ static void free_payload(struct payload *data) payload_cnt--; payload_version++; free_payload_data(data); + xfree(data->symtab); + xfree(data->strtab); xfree(data); } @@ -290,6 +296,8 @@ static int xsplice_upload(xen_sysctl_xsplice_upload_t *upload) err_raw: free_xenheap_pages(raw_data, get_order_from_bytes(upload->size)); err_data: + xfree(data->symtab); + xfree(data->strtab); xfree(data); return rc; } @@ -716,6 +724,24 @@ static int find_special_sections(struct payload *payload, for ( j = 0; j < 24; j ++ ) if ( f->pad[j] ) return -EINVAL; + + /* Lookup function's old address if not already resolved. */ + if ( !f->old_addr ) + { + f->old_addr = symbols_lookup_by_name(f->name); + if ( !f->old_addr ) + { + f->old_addr = xsplice_symbols_lookup_by_name(f->name); + if ( !f->old_addr ) + { + printk(XENLOG_ERR "%s: Could not resolve old address of %s\n", + elf->name, f->name); + return -ENOENT; + } + } + printk(XENLOG_DEBUG "%s: Resolved old address %s => 0x%"PRIx64"\n", + elf->name, f->name, f->old_addr); + } } sec = xsplice_elf_sec_by_name(elf, ".note.gnu.build-id"); @@ -798,6 +824,102 @@ static int find_special_sections(struct payload *payload, return 0; } +static bool_t is_core_symbol(struct xsplice_elf *elf, + struct xsplice_elf_sym *sym) +{ + if ( sym->sym->st_shndx == SHN_UNDEF || + sym->sym->st_shndx >= elf->hdr->e_shnum ) + return 0; + + return !!( (elf->sec[sym->sym->st_shndx].sec->sh_flags & SHF_ALLOC) && + (ELF64_ST_TYPE(sym->sym->st_info) == STT_OBJECT || + ELF64_ST_TYPE(sym->sym->st_info) == STT_FUNC) ); +} + +static int build_symbol_table(struct payload *payload, struct xsplice_elf *elf) +{ + unsigned int i, j, nsyms = 0; + size_t strtab_len = 0; + struct xsplice_symbol *symtab; + char *strtab; + + /* Recall that 0 is always NULL. */ + for ( i = 1; i < elf->nsym; i++ ) + { + if ( is_core_symbol(elf, elf->sym + i) ) + { + nsyms++; + strtab_len += strlen(elf->sym[i].name) + 1; + } + } + + symtab = xmalloc_array(struct xsplice_symbol, nsyms); + if ( !symtab ) + return -ENOMEM; + + strtab = xmalloc_bytes(strtab_len); + if ( !strtab ) + { + xfree(symtab); + return -ENOMEM; + } + + nsyms = 0; + strtab_len = 0; + for ( i = 1; i < elf->nsym; i++ ) + { + if ( is_core_symbol(elf, elf->sym + i) ) + { + symtab[nsyms].name = strtab + strtab_len; + symtab[nsyms].size = elf->sym[i].sym->st_size; + symtab[nsyms].value = elf->sym[i].sym->st_value; + symtab[nsyms].flags = 0; + strtab_len += strlcpy(strtab + strtab_len, elf->sym[i].name, + KSYM_NAME_LEN) + 1; + nsyms++; + } + } + + for ( i = 0; i < nsyms; i++ ) + { + bool_t found = 0; + + for ( j = 0; j < payload->nfuncs; j++ ) + { + if ( symtab[i].value == payload->funcs[j].new_addr ) + { + found = 1; + break; + } + } + + if ( !found ) + { + if ( xsplice_symbols_lookup_by_name(symtab[i].name) ) + { + printk(XENLOG_ERR "%s: duplicate new symbol: %s\n", elf->name, + symtab[i].name); + xfree(symtab); + xfree(strtab); + return -EEXIST; + } + printk(XENLOG_DEBUG "%s: new symbol %s\n", elf->name, + symtab[i].name); + } + else + { + printk(XENLOG_DEBUG "%s: overriding symbol %s\n", elf->name, + symtab[i].name); + } + } + + payload->symtab = symtab; + payload->strtab = strtab; + payload->nsyms = nsyms; + + return 0; +} + static int load_payload_data(struct payload *payload, uint8_t *raw, ssize_t len) { struct xsplice_elf elf; @@ -831,6 +953,10 @@ static int load_payload_data(struct payload *payload, uint8_t *raw, ssize_t len) if ( rc ) goto err_payload; + rc = build_symbol_table(payload, &elf); + if ( rc ) + goto err_payload; + rc = find_special_sections(payload, &elf); if ( rc ) goto err_payload; @@ -1234,6 +1360,31 @@ unsigned long search_module_extables(unsigned long addr) } #endif +uint64_t xsplice_symbols_lookup_by_name(const char *symname) +{ + struct payload *data; + unsigned int i; + uint64_t value = 0; + + spin_lock(&payload_lock); + + list_for_each_entry ( data, &payload_list, list ) + { + for ( i = 0; i < data->nsyms; i++ ) + { + if ( !strcmp(data->symtab[i].name, symname) ) + { + value = data->symtab[i].value; + goto out; + } + } + } + +out: + spin_unlock(&payload_lock); + return value; +} + static int __init xsplice_init(void) { register_keyhandler('x', xsplice_printall, "print xsplicing info", 1); diff --git a/xen/common/xsplice_elf.c b/xen/common/xsplice_elf.c index ad70797..dade9fd 100644 --- a/xen/common/xsplice_elf.c +++ b/xen/common/xsplice_elf.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -223,9 +224,21 @@ int xsplice_elf_resolve_symbols(struct xsplice_elf *elf) return_(-EINVAL); break; case SHN_UNDEF: - printk(XENLOG_ERR "%s: Unknown symbol: %s\n", elf->name, - elf->sym[i].name); - return_(-ENOENT); + elf->sym[i].sym->st_value = symbols_lookup_by_name(elf->sym[i].name); + if ( !elf->sym[i].sym->st_value ) + { + elf->sym[i].sym->st_value = + xsplice_symbols_lookup_by_name(elf->sym[i].name); + if ( !elf->sym[i].sym->st_value ) + { + printk(XENLOG_ERR "%s: Unknown symbol: %s\n", elf->name, + elf->sym[i].name); + return_(-ENOENT); + } + } + printk(XENLOG_DEBUG "%s: Undefined symbol resolved: %s => 0x%"PRIx64"\n", + elf->name, elf->sym[i].name, + elf->sym[i].sym->st_value); break; case SHN_ABS: printk(XENLOG_DEBUG "%s: Absolute symbol: %s => 0x%"PRIx64"\n", diff --git a/xen/include/xen/symbols.h b/xen/include/xen/symbols.h index 1fa0537..f8ea1dc 100644 --- a/xen/include/xen/symbols.h +++ b/xen/include/xen/symbols.h @@ -14,4 +14,6 @@ const char *symbols_lookup(unsigned long addr, int xensyms_read(uint32_t *symnum, char *type, uint64_t *address, char *name); +uint64_t symbols_lookup_by_name(const char *symname); + #endif /*_XEN_SYMBOLS_H*/ diff --git a/xen/include/xen/xsplice.h b/xen/include/xen/xsplice.h index 061a1a1..1045213 100644 --- a/xen/include/xen/xsplice.h +++ b/xen/include/xen/xsplice.h @@ -30,12 +30,19 @@ struct xsplice_build_id { unsigned int len; }; +struct xsplice_symbol { + const char *name; + uint64_t value; + size_t size; +}; + int xsplice_control(struct xen_sysctl_xsplice_op *); void do_xsplice(void); struct bug_frame *xsplice_find_bug(const char *eip, int *id); bool_t is_module(const void *addr); bool_t is_active_module_text(unsigned long addr); unsigned long search_module_extables(unsigned long addr); +uint64_t xsplice_symbols_lookup_by_name(const char *symname); /* Arch hooks */ int xsplice_verify_elf(struct xsplice_elf *elf, uint8_t *data);