@@ -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).
@@ -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),
@@ -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);
new file mode 100644
@@ -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__ */