|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v4 9/9] livepach: Add .livepatch.hooks functions and test-case
On Tue, Aug 23, 2016 at 10:22:12PM -0400, Konrad Rzeszutek Wilk wrote:
> From: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
>
> Add hook functions which run during patch apply and patch revert.
> Hook functions are used by livepatch payloads to manipulate data
> structures during patching, etc.
>
> One use case is the XSA91. As Martin mentions it:
> "If we have shadow variables, we also need an unload hook to garbage
> collect all the variables introduced by a hotpatch to prevent memory
> leaks. Potentially, we also want to pre-reserve memory for static or
> existing dynamic objects in the load-hook instead of on the fly.
>
> For testing and debugging, various applications are possible.
>
> In general, the hooks provide flexibility when having to deal with
> unforeseen cases, but their application should be rarely required (<
> 10%)."
>
> Furthermore include a test-case for it.
>
> Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
So... anybody willing to review it :-)
>
> ---
> Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
> Cc: George Dunlap <George.Dunlap@xxxxxxxxxxxxx>
> Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
> Cc: Jan Beulich <jbeulich@xxxxxxxx>
> Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx>
> Cc: Tim Deegan <tim@xxxxxxx>
> Cc: Wei Liu <wei.liu2@xxxxxxxxxx>
In regards to this going in v4.8 my recollection is that:
George: 0
Andrew: +1
Jan: 0 (with a slight leaning towards -1)?
I think that means folks are OK or 'don't care'.
And the livepatch maintainers:
Ross: +1 (obviously since he wrote it)
Konrad: +1
>
> v0.4..v0.11: Defered for v4.8
> v0.12: s/xsplice/livepatch/
>
> v3: Clarify the comments about spin_debug_enable
> Rename one of the hooks to lower-case (Z->z) to guarantee it being
> called last.
> Learned a lot of about 'const'
> v4: Do the actual const of the hooks.
> Remove the requirement for the tests-case hooks to be sorted
> (they never were to start with).
> Fix up the comment about spin_debug_enable so more.
> ---
> docs/misc/livepatch.markdown | 23 +++++++++++++++++
> xen/arch/x86/test/xen_hello_world.c | 34 +++++++++++++++++++++++++
> xen/common/livepatch.c | 50
> ++++++++++++++++++++++++++++++++++++-
> xen/include/xen/livepatch_payload.h | 49 ++++++++++++++++++++++++++++++++++++
> 4 files changed, 155 insertions(+), 1 deletion(-)
> create mode 100644 xen/include/xen/livepatch_payload.h
>
> diff --git a/docs/misc/livepatch.markdown b/docs/misc/livepatch.markdown
> index ad0df26..9f52aeb 100644
> --- a/docs/misc/livepatch.markdown
> +++ b/docs/misc/livepatch.markdown
> @@ -343,6 +343,13 @@ When reverting a patch, the hypervisor iterates over
> each `livepatch_func`
> and the core code copies the data from the undo buffer (private internal
> copy)
> to `old_addr`.
>
> +It optionally may contain the address of functions to be called right before
> +being applied and after being reverted:
> +
> + * `.livepatch.hooks.load` - an array of function pointers.
> + * `.livepatch.hooks.unload` - an array of function pointers.
> +
> +
> ### Example of .livepatch.funcs
>
> A simple example of what a payload file can be:
> @@ -380,6 +387,22 @@ struct livepatch_func livepatch_hello_world = {
>
> Code must be compiled with -fPIC.
>
> +### .livepatch.hooks.load and .livepatch.hooks.unload
> +
> +This section contains an array of function pointers to be executed
> +before payload is being applied (.livepatch.funcs) or after reverting
> +the payload. This is useful to prepare data structures that need to
> +be modified patching.
> +
> +Each entry in this array is eight bytes.
> +
> +The type definition of the function are as follow:
> +
> +<pre>
> +typedef void (*livepatch_loadcall_t)(void);
> +typedef void (*livepatch_unloadcall_t)(void);
> +</pre>
> +
> ### .livepatch.depends and .note.gnu.build-id
>
> To support dependencies checking and safe loading (to load the
> diff --git a/xen/arch/x86/test/xen_hello_world.c
> b/xen/arch/x86/test/xen_hello_world.c
> index 422bdf1..cb5e27a 100644
> --- a/xen/arch/x86/test/xen_hello_world.c
> +++ b/xen/arch/x86/test/xen_hello_world.c
> @@ -4,14 +4,48 @@
> */
>
> #include "config.h"
> +#include <xen/lib.h>
> #include <xen/types.h>
> #include <xen/version.h>
> #include <xen/livepatch.h>
> +#include <xen/livepatch_payload.h>
>
> #include <public/sysctl.h>
>
> static char hello_world_patch_this_fnc[] = "xen_extra_version";
> extern const char *xen_hello_world(void);
> +static unsigned int cnt;
> +
> +static void apply_hook(void)
> +{
> + printk(KERN_DEBUG "Hook executing.\n");
> +}
> +
> +static void revert_hook(void)
> +{
> + printk(KERN_DEBUG "Hook unloaded.\n");
> +}
> +
> +static void hi_func(void)
> +{
> + printk(KERN_DEBUG "%s: Hi! (called %u times)\n", __func__, ++cnt);
> +};
> +
> +static void check_fnc(void)
> +{
> + printk(KERN_DEBUG "%s: Hi func called %u times\n", __func__, cnt);
> + BUG_ON(cnt == 0 || cnt > 2);
> +}
> +
> +LIVEPATCH_LOAD_HOOK(apply_hook);
> +LIVEPATCH_UNLOAD_HOOK(revert_hook);
> +
> +/* Imbalance here. Two load and three unload. */
> +
> +LIVEPATCH_LOAD_HOOK(hi_func);
> +LIVEPATCH_UNLOAD_HOOK(hi_func);
> +
> +LIVEPATCH_UNLOAD_HOOK(check_fnc);
>
> struct livepatch_func __section(".livepatch.funcs")
> livepatch_xen_hello_world = {
> .version = LIVEPATCH_PAYLOAD_VERSION,
> diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
> index dd24a07..528c0c9 100644
> --- a/xen/common/livepatch.c
> +++ b/xen/common/livepatch.c
> @@ -23,6 +23,7 @@
> #include <xen/wait.h>
> #include <xen/livepatch_elf.h>
> #include <xen/livepatch.h>
> +#include <xen/livepatch_payload.h>
>
> #include <asm/event.h>
>
> @@ -73,7 +74,11 @@ struct payload {
> void **bss; /* .bss's of the payload. */
> size_t *bss_size; /* and their sizes. */
> size_t n_bss; /* Size of the array. */
> - char name[XEN_LIVEPATCH_NAME_SIZE]; /* Name of it. */
> + livepatch_loadcall_t *const *load_funcs; /* The array of funcs to call
> after */
> + livepatch_unloadcall_t *const *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_LIVEPATCH_NAME_SIZE]; /* Name of it. */
> };
>
> /* Defines an outstanding patching action. */
> @@ -583,6 +588,25 @@ static int prepare_payload(struct payload *payload,
> return rc;
> }
>
> + sec = livepatch_elf_sec_by_name(elf, ".livepatch.hooks.load");
> + if ( sec )
> + {
> + if ( sec->sec->sh_size % sizeof(*payload->load_funcs) )
> + return -EINVAL;
> +
> + payload->load_funcs = sec->load_addr;
> + payload->n_load_funcs = sec->sec->sh_size /
> sizeof(*payload->load_funcs);
> + }
> +
> + sec = livepatch_elf_sec_by_name(elf, ".livepatch.hooks.unload");
> + if ( sec )
> + {
> + if ( sec->sec->sh_size % sizeof(*payload->unload_funcs) )
> + return -EINVAL;
> +
> + payload->unload_funcs = sec->load_addr;
> + payload->n_unload_funcs = sec->sec->sh_size /
> sizeof(*payload->unload_funcs);
> + }
> sec = livepatch_elf_sec_by_name(elf, ELF_BUILD_ID_NOTE);
> if ( sec )
> {
> @@ -1071,6 +1095,18 @@ static int apply_payload(struct payload *data)
>
> arch_livepatch_quiesce();
>
> + /*
> + * Since we are running with IRQs disabled and the hooks may call common
> + * code - which expects certain spinlocks to run with IRQs enabled - we
> + * temporarily disable the spin locks IRQ state checks.
> + */
> + spin_debug_disable();
> + for ( i = 0; i < data->n_load_funcs; i++ )
> + data->load_funcs[i]();
> + spin_debug_enable();
> +
> + ASSERT(!local_irq_is_enabled());
> +
> for ( i = 0; i < data->nfuncs; i++ )
> arch_livepatch_apply_jmp(&data->funcs[i]);
>
> @@ -1097,6 +1133,18 @@ static int revert_payload(struct payload *data)
> for ( i = 0; i < data->nfuncs; i++ )
> arch_livepatch_revert_jmp(&data->funcs[i]);
>
> + /*
> + * Since we are running with IRQs disabled and the hooks may call common
> + * code - which expects certain spinlocks to run with IRQs enabled - we
> + * temporarily disable the spin locks IRQ state checks.
> + */
> + spin_debug_disable();
> + for ( i = 0; i < data->n_unload_funcs; i++ )
> + data->unload_funcs[i]();
> + spin_debug_enable();
> +
> + ASSERT(!local_irq_is_enabled());
> +
> arch_livepatch_revive();
>
> /*
> diff --git a/xen/include/xen/livepatch_payload.h
> b/xen/include/xen/livepatch_payload.h
> new file mode 100644
> index 0000000..8f38cc2
> --- /dev/null
> +++ b/xen/include/xen/livepatch_payload.h
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright (C) 2016 Citrix Systems R&D Ltd.
> + */
> +
> +#ifndef __XEN_LIVEPATCH_PAYLOAD_H__
> +#define __XEN_LIVEPATCH_PAYLOAD_H__
> +
> +/*
> + * The following definitions are to be used in patches. They are taken
> + * from kpatch.
> + */
> +typedef void livepatch_loadcall_t(void);
> +typedef void livepatch_unloadcall_t(void);
> +
> +/*
> + * LIVEPATCH_LOAD_HOOK macro
> + *
> + * Declares a function pointer to be allocated in a new
> + * .livepatch.hook.load section. This livepatch_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
> + * .livepatch.hook.load section is a table of functions that will be
> + * executed in series by the livepatch infrastructure at patch load time.
> + */
> +#define LIVEPATCH_LOAD_HOOK(_fn) \
> + livepatch_loadcall_t *__attribute__((weak)) \
> + const livepatch_load_data_##_fn __section(".livepatch.hooks.load") =
> _fn;
> +
> +/*
> + * LIVEPATCH_UNLOAD_HOOK macro
> + *
> + * Same as LOAD hook with s/load/unload/
> + */
> +#define LIVEPATCH_UNLOAD_HOOK(_fn) \
> + livepatch_unloadcall_t *__attribute__((weak)) \
> + const livepatch_unload_data_##_fn
> __section(".livepatch.hooks.unload") = _fn;
> +
> +#endif /* __XEN_LIVEPATCH_PAYLOAD_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> --
> 2.4.11
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |