[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v4 21/34] xsplice: Add .xsplice.hooks functions and test-case



From: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>

Add hook functions which run during patch apply and patch revert.
Hook functions are used by xsplice payloads to manipulate data structures
during patching, etc.

Also add macros to be used by payloads for excluding functions or
sections from being included in a patch.

Furthermore include a test-case for it.

Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>

---
Cc: Keir Fraser <keir@xxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxx>
Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>

v2: Style guide changes
v3: Include the test-case - and also re-order this patch
---
 docs/misc/xsplice.markdown          | 21 +++++++++++++
 xen/arch/x86/test/xen_hello_world.c | 15 ++++++++++
 xen/common/xsplice.c                | 37 +++++++++++++++++++++++
 xen/include/xen/xsplice_patch.h     | 59 +++++++++++++++++++++++++++++++++++++
 4 files changed, 132 insertions(+)
 create mode 100644 xen/include/xen/xsplice_patch.h

diff --git a/docs/misc/xsplice.markdown b/docs/misc/xsplice.markdown
index e7c41da..d1f2a5b 100644
--- a/docs/misc/xsplice.markdown
+++ b/docs/misc/xsplice.markdown
@@ -285,6 +285,12 @@ like what the Linux kernel module loader does.
 
 The payload contains a section (xsplice_patch_func) with an array of structures
 describing the functions to be patched:
+It optionally may contain the address of functions to be called right before
+being applied and after being reverted:
+
+ * `.xsplice.hooks.load` - an array of function pointers.
+ * `.xsplice.hooks.unload` - an array of function pointers.
+
 
 <pre>
 struct xsplice_patch_func {  
@@ -362,6 +368,21 @@ struct xsplice_patch_func xsplice_hello_world = {
 
 Code must be compiled with -fPIC.
 
+
+### .xsplice.hooks.load and .xsplice.hooks.unload
+
+This section contains an array of function pointers to be executed
+before payload is being applied (.xsplice.funcs) or after reverting
+the payload.
+
+Each entry in this array is eight bytes.
+
+The type definition of the function are as follow:
+
+<pre>
+typedef void (*xsplice_loadcall_t)(void);  
+typedef void (*xsplice_unloadcall_t)(void);   
+</pre>
 ## Hypercalls
 
 We will employ the sub operations of the system management hypercall (sysctl).
diff --git a/xen/arch/x86/test/xen_hello_world.c 
b/xen/arch/x86/test/xen_hello_world.c
index 243eb3f..d2b3cc2 100644
--- a/xen/arch/x86/test/xen_hello_world.c
+++ b/xen/arch/x86/test/xen_hello_world.c
@@ -5,8 +5,10 @@
 
 #include <xen/config.h>
 #include <xen/types.h>
+#include <xen/xsplice_patch.h>
 #include <xen/xsplice.h>
 #include "config.h"
+#include <xen/lib.h>
 
 static char xen_hello_world_name[] = "xen_hello_world";
 extern const char *xen_hello_world(void);
@@ -14,6 +16,19 @@ extern const char *xen_hello_world(void);
 /* External symbol. */
 extern const char *xen_extra_version(void);
 
+void apply_hook(void)
+{
+    printk(KERN_DEBUG "Hook executing.\n");
+}
+
+void revert_hook(void)
+{
+    printk(KERN_DEBUG "Hook unloaded.\n");
+}
+
+XSPLICE_LOAD_HOOK(apply_hook);
+XSPLICE_UNLOAD_HOOK(revert_hook);
+
 struct xsplice_patch_func __section(".xsplice.funcs") xsplice_xen_hello_world 
= {
     .name = xen_hello_world_name,
     .new_addr = (unsigned long)(xen_hello_world),
diff --git a/xen/common/xsplice.c b/xen/common/xsplice.c
index a3366ef..5fb1867 100644
--- a/xen/common/xsplice.c
+++ b/xen/common/xsplice.c
@@ -20,6 +20,7 @@
 #include <xen/wait.h>
 #include <xen/xsplice_elf.h>
 #include <xen/xsplice.h>
+#include <xen/xsplice_patch.h>
 
 #include <asm/event.h>
 #include <asm/nmi.h>
@@ -56,6 +57,10 @@ struct payload {
     struct xsplice_symbol *symtab;       /* All symbols. */
     char *strtab;                        /* Pointer to .strtab. */
     unsigned int nsyms;                  /* Nr of entries in .strtab and 
symbols. */
+    xsplice_loadcall_t *load_funcs;      /* The array of funcs to call after */
+    xsplice_unloadcall_t *unload_funcs;  /* load and unload of the payload. */
+    unsigned int n_load_funcs;           /* Nr of the funcs to load and 
execute. */
+    unsigned int n_unload_funcs;         /* Nr of funcs to call durung unload. 
*/
     char name[XEN_XSPLICE_NAME_SIZE + 1];/* Name of it. */
 };
 
@@ -433,6 +438,28 @@ static int prepare_payload(struct payload *payload,
         }
     }
 
+    sec = xsplice_elf_sec_by_name(elf, ".xsplice.hooks.load");
+    if ( sec )
+    {
+        if ( !sec->sec->sh_size ||
+             (sec->sec->sh_size % sizeof (*payload->load_funcs)) )
+            return -EINVAL;
+
+        payload->load_funcs = (xsplice_loadcall_t *)sec->load_addr;
+        payload->n_load_funcs = sec->sec->sh_size / (sizeof 
*payload->load_funcs);
+    }
+
+    sec = xsplice_elf_sec_by_name(elf, ".xsplice.hooks.unload");
+    if ( sec )
+    {
+        if ( !sec->sec->sh_size ||
+             (sec->sec->sh_size % sizeof (*payload->unload_funcs)) )
+            return -EINVAL;
+
+        payload->unload_funcs = (xsplice_unloadcall_t *)sec->load_addr;
+        payload->n_unload_funcs = sec->sec->sh_size / (sizeof 
*payload->unload_funcs);
+    }
+
     /* Setup the virtual region with proper data. */
     region = &payload->bug_ex_region;
     region->skip = ignore_region;
@@ -769,6 +796,11 @@ static int apply_payload(struct payload *data)
 
     arch_xsplice_patching_leave();
 
+    spin_debug_disable();
+    for ( i = 0; i < data->n_load_funcs; i++ )
+        data->load_funcs[i]();
+    spin_debug_enable();
+
     list_add_tail(&data->applied_list, &applied_list);
     register_virtual_region(&data->bug_ex_region);
 
@@ -792,6 +824,11 @@ static int revert_payload(struct payload *data)
 
     arch_xsplice_patching_leave();
 
+    spin_debug_disable();
+    for ( i = 0; i < data->n_unload_funcs; i++ )
+        data->unload_funcs[i]();
+    spin_debug_enable();
+
     list_del_init(&data->applied_list);
     unregister_virtual_region(&data->bug_ex_region);
 
diff --git a/xen/include/xen/xsplice_patch.h b/xen/include/xen/xsplice_patch.h
new file mode 100644
index 0000000..19d3f76
--- /dev/null
+++ b/xen/include/xen/xsplice_patch.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 Citrix Systems R&D Ltd.
+ */
+
+#ifndef __XEN_XSPLICE_PATCH_H__
+#define __XEN_XSPLICE_PATCH_H__
+
+/*
+ * The following definitions are to be used in patches. They are taken
+ * from kpatch.
+ */
+typedef void (*xsplice_loadcall_t)(void);
+typedef void (*xsplice_unloadcall_t)(void);
+
+/* This definition is taken from Linux. */
+#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
+/*
+ * XSPLICE_IGNORE_SECTION macro
+ *
+ * This macro is for ignoring sections that may change as a side effect of
+ * another change or might be a non-bundlable section; that is one that does
+ * not honor -ffunction-section and create a one-to-one relation from function
+ * symbol to section.
+ */
+#define XSPLICE_IGNORE_SECTION(_sec) \
+       char *__UNIQUE_ID(xsplice_ignore_section_) 
__section(".xsplice.ignore.sections") = _sec;
+
+/*
+ * XSPLICE_IGNORE_FUNCTION macro
+ *
+ * This macro is for ignoring functions that may change as a side effect of a
+ * change in another function.
+ */
+#define XSPLICE_IGNORE_FUNCTION(_fn) \
+       void *__xsplice_ignore_func_##_fn 
__section(".xsplice.ignore.functions") = _fn;
+
+/*
+ * XSPLICE_LOAD_HOOK macro
+ *
+ * Declares a function pointer to be allocated in a new
+ * .xsplice.hook.load section.  This xsplice_load_data symbol is later
+ * stripped by create-diff-object so that it can be declared in multiple
+ * objects that are later linked together, avoiding global symbol
+ * collision.  Since multiple hooks can be registered, the
+ * .xsplice.hook.load section is a table of functions that will be
+ * executed in series by the xsplice infrastructure at patch load time.
+ */
+#define XSPLICE_LOAD_HOOK(_fn) \
+       xsplice_loadcall_t __attribute__((weak)) xsplice_load_data 
__section(".xsplice.hooks.load") = _fn;
+
+/*
+ * XSPLICE_UNLOAD_HOOK macro
+ *
+ * Same as LOAD hook with s/load/unload/
+ */
+#define XSPLICE_UNLOAD_HOOK(_fn) \
+       xsplice_unloadcall_t __attribute__((weak)) xsplice_unload_data 
__section(".xsplice.hooks.unload") = _fn;
+
+#endif /* __XEN_XSPLICE_PATCH_H__ */
-- 
2.5.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.