From patchwork Thu Jan 14 21:47:08 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: 8035811 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 E0483BEEED for ; Thu, 14 Jan 2016 21:50:33 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C86DE204F6 for ; Thu, 14 Jan 2016 21:50:32 +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 4C279204EB for ; Thu, 14 Jan 2016 21:50:31 +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 1aJpjy-0006Yc-R8; Thu, 14 Jan 2016 21:47:34 +0000 Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1aJpjv-0006UH-HU for xen-devel@lists.xenproject.org; Thu, 14 Jan 2016 21:47:31 +0000 Received: from [193.109.254.147] by server-7.bemta-14.messagelabs.com id B6/8A-28221-27718965; Thu, 14 Jan 2016 21:47:30 +0000 X-Env-Sender: konrad@char.us.oracle.com X-Msg-Ref: server-10.tower-27.messagelabs.com!1452808048!16981074!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 30273 invoked from network); 14 Jan 2016 21:47:29 -0000 Received: from aserp1040.oracle.com (HELO aserp1040.oracle.com) (141.146.126.69) by server-10.tower-27.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 14 Jan 2016 21:47:29 -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 u0ELlLDK014876 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Thu, 14 Jan 2016 21:47:21 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u0ELlKKm023664 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Thu, 14 Jan 2016 21:47:20 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u0ELlK6f003173; Thu, 14 Jan 2016 21:47:20 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 9AEA46A4DB1; 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:08 -0500 Message-Id: <1452808031-706-11-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 10/13] xen_hello_world.xsplice: Test payload for patching 'xen_extra_version'. 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 This change demonstrates how to generate an xSplice ELF payload. The idea here is that we want to patch in the hypervisor the 'xen_version_extra' function with an function that will return 'Hello World'. The 'xl info | grep extraversion' will reflect the new value after the patching. To generate this ELF payload file we need: - C code of the new code. - C code generating the .xsplice.func structure. - The address of the old code (xen_extra_version). We do it by using 'nm' but that is a bit of hack. The linker script file: - Discards .debug* and .comments* sections. - Changes the name of .data.local.xsplice_hello_world to .xsplice.func - Figures out the size of the new code. Also if you are curious on the input/output sections magic the linker does, add these to the GCC line: -Wl,-M -Wl,-t -Wl,-verbose which are: print linking map, provide trace and be verbose. The use-case is simple: $xen-xsplice load /usr/lib/xen/bin/xen_hello_world.xsplice $xen-xsplice list ID | status ----------------------------------------+------------ xen_hello_world APPLIED $xl info | grep extra xen_extra : Hello World $xen-xsplice revert xen_hello_world Performing revert: completed $xen-xsplice unload xen_hello_world Performing unload: completed $xl info | grep extra xen_extra : -unstable Note that it does not build under a 32-bit toolstack as there is no access to the hypervisor (xen-syms). We also force it to be built every time - as the hypervisor may have been rebuilt. Signed-off-by: Konrad Rzeszutek Wilk --- docs/misc/xsplice.markdown | 50 ++++++++++++++++++++++++++++++++++++++++++++ tools/misc/Makefile | 25 +++++++++++++++++++++- tools/misc/xen_hello_world.c | 15 +++++++++++++ tools/misc/xsplice.h | 12 +++++++++++ tools/misc/xsplice.lds | 11 ++++++++++ 5 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 tools/misc/xen_hello_world.c create mode 100644 tools/misc/xsplice.h create mode 100644 tools/misc/xsplice.lds diff --git a/docs/misc/xsplice.markdown b/docs/misc/xsplice.markdown index beb452e..e2cdcff 100644 --- a/docs/misc/xsplice.markdown +++ b/docs/misc/xsplice.markdown @@ -312,11 +312,61 @@ size. When applying the patch the hypervisor iterates over each `xsplice_patch_func` structure and the core code inserts a trampoline at `old_addr` to `new_addr`. +The `new_addr` is altered when the ELF payload is loaded. When reverting a patch, the hypervisor iterates over each `xsplice_patch_func` and the core code copies the data from the undo buffer (private internal copy) to `old_addr`. +### Example + +A simple example of what a payload file can be: + +
+/* MUST be in sync with hypervisor. */  
+struct xsplice_patch_func {  
+    const char *name;  
+    unsigned long new_addr;  
+    const unsigned long old_addr;  
+    uint32_t new_size;  
+    const uint32_t old_size;  
+    uint8_t pad[32];  
+};  
+
+/* Our replacement function for xen_extra_version. */  
+const char *xen_hello_world(void)  
+{  
+    return "Hello World";  
+}  
+
+struct xsplice_patch_func xsplice_hello_world = {  
+    .name = "xen_extra_version",  
+    .new_addr = &xen_hello_world,  
+    .old_addr = 0xffff82d08013963c, /* Extracted from xen-syms. */  
+    .new_size = 13, /* To be be computed by scripts. */  
+    .old_size = 13, /* -----------""---------------  */  
+};  
+
+ +With the linker script as follow to change the `xsplice_hello_world` +do be `.xsplice.funcs` : + +
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")  
+OUTPUT_ARCH(i386:x86-64)  
+ENTRY(xsplice_hello_world)  
+SECTIONS  
+{  
+    /* The hypervisor expects ".xsplice.func", so change  
+     * the ".data.xsplice_hello_world" to it. */  
+
+    .xsplice.funcs : { *(*.xsplice_hello_world) }  
+    }  
+}  
+
+ +Code must be compiled with -fPIC. + ## Hypercalls We will employ the sub operations of the system management hypercall (sysctl). diff --git a/tools/misc/Makefile b/tools/misc/Makefile index c46873e..8385830 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -36,6 +36,10 @@ INSTALL_SBIN += $(INSTALL_SBIN-y) # Everything to be installed in a private bin/ INSTALL_PRIVBIN += xenpvnetboot +# We need the hypervisor - and only 64-bit builds have it. +ifeq ($(XEN_COMPILE_ARCH),x86_64) +INSTALL_PRIVBIN += xen_hello_world.xsplice +endif # Everything to be installed TARGETS_ALL := $(INSTALL_BIN) $(INSTALL_SBIN) $(INSTALL_PRIVBIN) @@ -49,7 +53,7 @@ TARGETS_COPY += xenpvnetboot # Everything which needs to be built TARGETS_BUILD := $(filter-out $(TARGETS_COPY),$(TARGETS_ALL)) -.PHONY: all build +.PHONY: all build xsplice all build: $(TARGETS_BUILD) .PHONY: install @@ -111,4 +115,23 @@ gtraceview: gtraceview.o xencov: xencov.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) +.PHONY: xsplice +xsplice: +ifeq ($(XEN_COMPILE_ARCH),x86_64) + # We MUST regenerate the file everytime we build - in case the hypervisor + # is rebuilt too. + $(RM) *.xplice + $(MAKE) xen_hello_world.xsplice +endif + +XEN_EXTRA_VERSION_ADDR=$(shell nm --defined $(XEN_ROOT)/xen/xen-syms | grep xen_extra_version | awk '{print "0x"$$1}') + +xen_hello_world.xsplice: xen_hello_world.c + $(CC) -DOLD_CODE=$(XEN_EXTRA_VERSION_ADDR) -I$(XEN_ROOT)/tools/include \ + -fPIC -Wl,--emit-relocs \ + -Wl,-r -Wl,--entry=xsplice_hello_world \ + -fdata-sections -ffunction-sections \ + -nostdlib -Txsplice.lds \ + -o $@ $< + @objdump -x --section=.xsplice.funcs $@ -include $(DEPS) diff --git a/tools/misc/xen_hello_world.c b/tools/misc/xen_hello_world.c new file mode 100644 index 0000000..8c24d8f --- /dev/null +++ b/tools/misc/xen_hello_world.c @@ -0,0 +1,15 @@ +#include "xsplice.h" + +/* Our replacement function for xen_extra_version. */ +const char *xen_hello_world(void) +{ + return "Hello World"; +} + +struct xsplice_patch_func xsplice_hello_world = { + .name = "xen_extra_version", + .new_addr = &xen_hello_world, + .old_addr = OLD_CODE, + .new_size = 13, /* TODO: Compute. */ + .old_size = 13, /* TODO: Compute. */ +}; diff --git a/tools/misc/xsplice.h b/tools/misc/xsplice.h new file mode 100644 index 0000000..6ce8bae --- /dev/null +++ b/tools/misc/xsplice.h @@ -0,0 +1,12 @@ +#include +#include + +/* MUST be in sync with hypervisor. */ +struct xsplice_patch_func { + const char *name; + unsigned long new_addr; + const unsigned long old_addr; + uint32_t new_size; + const uint32_t old_size; + uint8_t pad[32]; +}; diff --git a/tools/misc/xsplice.lds b/tools/misc/xsplice.lds new file mode 100644 index 0000000..f52eb8c --- /dev/null +++ b/tools/misc/xsplice.lds @@ -0,0 +1,11 @@ +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(xsplice_hello_world) +SECTIONS +{ + /* The hypervisor expects ".xsplice.func", so change + * the ".data.xsplice_hello_world" to it. */ + + .xsplice.funcs : { *(*.xsplice_hello_world) } + +}