[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 07/12] livepatch: Add per-function applied/reverted state tracking marker
Livepatch only tracks an entire payload applied/reverted state. But, with an option to supply the apply_payload() and/or revert_payload() functions as optional hooks, it becomes possible to intermix the execution of the original apply_payload()/revert_payload() functions with their dynamically supplied counterparts. It is important then to track the current state of every function being patched and prevent situations of unintentional double-apply or unapplied revert. To support that, it is necessary to extend public interface of the livepatch. The struct livepatch_func gets additional field holding the applied/reverted state marker. To reflect the livepatch payload ABI change, bump the version flag LIVEPATCH_PAYLOAD_VERSION up to 2. [And also update the top of the design document] Signed-off-by: Pawel Wieczorkiewicz <wipawel@xxxxxxxxx> Reviewed-by: Andra-Irina Paraschiv <andraprs@xxxxxxxxxx> Reviewed-by: Bjoern Doebel <doebel@xxxxxxxxx> Reviewed-by: Martin Pohlack <mpohlack@xxxxxxxxx> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> Acked-by: Julien Grall <julien.grall@xxxxxxx> --- Changed since v2: * Documentation fixes Changed since v1: * support the feature for all arch (add handling for Arm) * add common is_func_applied() and is_func_reverted() to be used by all arch * remove explicit enum values from enum livepatch_func_state * added corresponding documentation * added tests docs/misc/livepatch.pandoc | 17 ++- xen/arch/arm/arm32/livepatch.c | 12 ++- xen/arch/arm/arm64/livepatch.c | 12 ++- xen/arch/arm/livepatch.c | 10 +- xen/arch/x86/livepatch.c | 22 +++- xen/common/livepatch.c | 35 ++++++ xen/include/public/sysctl.h | 9 +- xen/include/xen/livepatch.h | 27 ++++- xen/test/livepatch/Makefile | 27 ++++- xen/test/livepatch/xen_action_hooks.c | 2 + xen/test/livepatch/xen_action_hooks_marker.c | 112 +++++++++++++++++++ xen/test/livepatch/xen_action_hooks_noapply.c | 136 +++++++++++++++++++++++ xen/test/livepatch/xen_action_hooks_norevert.c | 143 +++++++++++++++++++++++++ 13 files changed, 554 insertions(+), 10 deletions(-) create mode 100644 xen/test/livepatch/xen_action_hooks_marker.c create mode 100644 xen/test/livepatch/xen_action_hooks_noapply.c create mode 100644 xen/test/livepatch/xen_action_hooks_norevert.c diff --git a/docs/misc/livepatch.pandoc b/docs/misc/livepatch.pandoc index 6fafb9e4b1..383a988ba2 100644 --- a/docs/misc/livepatch.pandoc +++ b/docs/misc/livepatch.pandoc @@ -1,4 +1,4 @@ -# Xen Live Patching Design v1 +# Xen Live Patching Design v2 ## Rationale @@ -297,10 +297,14 @@ which describe the functions to be patched: uint32_t old_size; uint8_t version; uint8_t opaque[31]; + /* Added to livepatch payload version 2: */ + uint8_t applied; + uint8_t _pad[7]; }; The size of the structure is 64 bytes on 64-bit hypervisors. It will be 52 on 32-bit hypervisors. +The version 2 of the payload adds additional 8 bytes to the structure size. * `name` is the symbol name of the old function. Only used if `old_addr` is zero, otherwise will be used during dynamic linking (when hypervisor loads @@ -324,9 +328,15 @@ The size of the structure is 64 bytes on 64-bit hypervisors. It will be * If the value of `new_addr` is zero then `new_size` determines how many instruction bytes to NOP (up to opaque size modulo smallest platform instruction - 1 byte x86 and 4 bytes on ARM). - * `version` is to be one. + * `version` indicates version of the generated payload. * `opaque` **MUST** be zero. +The version 2 of the payload adds the following fields to the structure: + + * `applied` tracks function's applied/reverted state. It has a boolean type + either LIVEPATCH_FUNC_NOT_APPLIED or LIVEPATCH_FUNC_APPLIED. + * `_pad[7]` adds padding to align to 8 bytes. + The size of the `livepatch_func` array is determined from the ELF section size. @@ -378,6 +388,9 @@ A simple example of what a payload file can be: uint32_t old_size; uint8_t version; uint8_t pad[31]; + /* Added to livepatch payload version 2: */ + uint8_t applied; + uint8_t _pad[7]; }; /* Our replacement function for xen_extra_version. */ diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c index 41378a54ae..76780d69bf 100644 --- a/xen/arch/arm/arm32/livepatch.c +++ b/xen/arch/arm/arm32/livepatch.c @@ -22,9 +22,16 @@ void arch_livepatch_apply(struct livepatch_func *func) ASSERT(vmap_of_xen_text); + /* + * If the apply action has been already executed + * on this function, do nothing... + */ + if ( is_func_applied(func) ) + return; + len = livepatch_insn_len(func); if ( !len ) - return; + goto applied; /* Save old ones. */ memcpy(func->opaque, func->old_addr, len); @@ -73,6 +80,9 @@ void arch_livepatch_apply(struct livepatch_func *func) if ( func->new_addr ) clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size); clean_and_invalidate_dcache_va_range(new_ptr, sizeof (*new_ptr) * len); + +applied: + func->applied = LIVEPATCH_FUNC_APPLIED; } /* arch_livepatch_revert shared with ARM 32/ARM 64. */ diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c index 5c75779284..61a764816c 100644 --- a/xen/arch/arm/arm64/livepatch.c +++ b/xen/arch/arm/arm64/livepatch.c @@ -26,9 +26,16 @@ void arch_livepatch_apply(struct livepatch_func *func) ASSERT(vmap_of_xen_text); + /* + * If the apply action has been already executed + * on this function, do nothing... + */ + if ( is_func_applied(func) ) + return; + len = livepatch_insn_len(func); if ( !len ) - return; + goto applied; /* Save old ones. */ memcpy(func->opaque, func->old_addr, len); @@ -60,6 +67,9 @@ void arch_livepatch_apply(struct livepatch_func *func) if ( func->new_addr ) clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size); clean_and_invalidate_dcache_va_range(new_ptr, sizeof (*new_ptr) * len); + +applied: + func->applied = LIVEPATCH_FUNC_APPLIED; } /* arch_livepatch_revert shared with ARM 32/ARM 64. */ diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c index 279d52cc6c..022402d55f 100644 --- a/xen/arch/arm/livepatch.c +++ b/xen/arch/arm/livepatch.c @@ -73,17 +73,25 @@ int arch_livepatch_verify_func(const struct livepatch_func *func) return 0; } -void arch_livepatch_revert(const struct livepatch_func *func) +void arch_livepatch_revert(struct livepatch_func *func) { uint32_t *new_ptr; unsigned int len; + /* + * If the apply action hasn't been executed + * on this function, do nothing... + */ + if ( is_func_reverted(func) ) + return; + new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text; len = livepatch_insn_len(func); memcpy(new_ptr, func->opaque, len); clean_and_invalidate_dcache_va_range(new_ptr, len); + func->applied = LIVEPATCH_FUNC_NOT_APPLIED; } void arch_livepatch_post_action(void) diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c index c82cf53b9e..5701c90e48 100644 --- a/xen/arch/x86/livepatch.c +++ b/xen/arch/x86/livepatch.c @@ -56,10 +56,17 @@ void noinline arch_livepatch_apply(struct livepatch_func *func) uint8_t insn[sizeof(func->opaque)]; unsigned int len; + /* + * If the apply action has been already executed + * on this function, do nothing... + */ + if ( is_func_applied(func) ) + return; + old_ptr = func->old_addr; len = livepatch_insn_len(func); if ( !len ) - return; + goto applied; memcpy(func->opaque, old_ptr, len); if ( func->new_addr ) @@ -77,15 +84,26 @@ void noinline arch_livepatch_apply(struct livepatch_func *func) add_nops(insn, len); memcpy(old_ptr, insn, len); + +applied: + func->applied = LIVEPATCH_FUNC_APPLIED; } /* * "noinline" to cause control flow change and thus invalidate I$ and * cause refetch after modification. */ -void noinline arch_livepatch_revert(const struct livepatch_func *func) +void noinline arch_livepatch_revert(struct livepatch_func *func) { + /* + * If the apply action hasn't been executed + * on this function, do nothing... + */ + if ( is_func_reverted(func) ) + return; + memcpy(func->old_addr, func->opaque, livepatch_insn_len(func)); + func->applied = LIVEPATCH_FUNC_NOT_APPLIED; } /* diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c index 705b5b8151..d76619844c 100644 --- a/xen/common/livepatch.c +++ b/xen/common/livepatch.c @@ -1240,6 +1240,29 @@ static inline void revert_payload_tail(struct payload *data) data->state = LIVEPATCH_STATE_CHECKED; } +/* + * Check if an action has applied the same state to all payload's functions consistently. + */ +static inline bool was_action_consistent(const struct payload *data, livepatch_func_state_t expected_state) +{ + int i; + + for ( i = 0; i < data->nfuncs; i++ ) + { + struct livepatch_func *f = &(data->funcs[i]); + + if ( f->applied != expected_state ) + { + printk(XENLOG_ERR LIVEPATCH "%s: Payload has a function: '%s' with inconsistent applied state.\n", + data->name, f->name ?: "noname"); + + return false; + } + } + + return true; +} + /* * This function is executed having all other CPUs with no deep stack (we may * have cpu_idle on it) and IRQs disabled. @@ -1266,6 +1289,9 @@ static void livepatch_do_action(void) else rc = apply_payload(data); + if ( !was_action_consistent(data, rc ? LIVEPATCH_FUNC_NOT_APPLIED : LIVEPATCH_FUNC_APPLIED) ) + panic("livepatch: partially applied payload '%s'!\n", data->name); + if ( rc == 0 ) apply_payload_tail(data); break; @@ -1280,6 +1306,9 @@ static void livepatch_do_action(void) else rc = revert_payload(data); + if ( !was_action_consistent(data, rc ? LIVEPATCH_FUNC_APPLIED : LIVEPATCH_FUNC_NOT_APPLIED) ) + panic("livepatch: partially reverted payload '%s'!\n", data->name); + if ( rc == 0 ) revert_payload_tail(data); break; @@ -1302,6 +1331,9 @@ static void livepatch_do_action(void) other->rc = revert_payload(other); + if ( !was_action_consistent(other, rc ? LIVEPATCH_FUNC_APPLIED : LIVEPATCH_FUNC_NOT_APPLIED) ) + panic("livepatch: partially reverted payload '%s'!\n", other->name); + if ( other->rc == 0 ) revert_payload_tail(other); else @@ -1322,6 +1354,9 @@ static void livepatch_do_action(void) else rc = apply_payload(data); + if ( !was_action_consistent(data, rc ? LIVEPATCH_FUNC_NOT_APPLIED : LIVEPATCH_FUNC_APPLIED) ) + panic("livepatch: partially applied payload '%s'!\n", data->name); + if ( rc == 0 ) apply_payload_tail(data); } diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index 1b2b165a6d..3bcb892ce1 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -818,7 +818,7 @@ struct xen_sysctl_cpu_featureset { * If zero exit with success. */ -#define LIVEPATCH_PAYLOAD_VERSION 1 +#define LIVEPATCH_PAYLOAD_VERSION 2 /* * .livepatch.funcs structure layout defined in the `Payload format` * section in the Live Patch design document. @@ -826,6 +826,11 @@ struct xen_sysctl_cpu_featureset { * We guard this with __XEN__ as toolstacks SHOULD not use it. */ #ifdef __XEN__ +typedef enum livepatch_func_state { + LIVEPATCH_FUNC_NOT_APPLIED, + LIVEPATCH_FUNC_APPLIED +} livepatch_func_state_t; + struct livepatch_func { const char *name; /* Name of function to be patched. */ void *new_addr; @@ -834,6 +839,8 @@ struct livepatch_func { uint32_t old_size; uint8_t version; /* MUST be LIVEPATCH_PAYLOAD_VERSION. */ uint8_t opaque[31]; + uint8_t applied; + uint8_t _pad[7]; }; typedef struct livepatch_func livepatch_func_t; #endif diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h index 2aec532ee2..28f9536776 100644 --- a/xen/include/xen/livepatch.h +++ b/xen/include/xen/livepatch.h @@ -109,6 +109,31 @@ static inline int livepatch_verify_distance(const struct livepatch_func *func) return 0; } + +static inline bool_t is_func_applied(const struct livepatch_func *func) +{ + if ( func->applied == LIVEPATCH_FUNC_APPLIED ) + { + printk(XENLOG_WARNING LIVEPATCH "%s: %s has been already applied before\n", + __func__, func->name); + return true; + } + + return false; +} + +static inline bool_t is_func_reverted(const struct livepatch_func *func) +{ + if ( !func->old_addr || func->applied == LIVEPATCH_FUNC_NOT_APPLIED ) + { + printk(XENLOG_WARNING LIVEPATCH "%s: %s has not been applied before\n", + __func__, func->name); + return true; + } + + return false; +} + /* * These functions are called around the critical region patching live code, * for an architecture to take make appropratie global state adjustments. @@ -117,7 +142,7 @@ int arch_livepatch_quiesce(void); void arch_livepatch_revive(void); void arch_livepatch_apply(struct livepatch_func *func); -void arch_livepatch_revert(const struct livepatch_func *func); +void arch_livepatch_revert(struct livepatch_func *func); void arch_livepatch_post_action(void); void arch_livepatch_mask(void); diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile index bbc6bdaf64..23113d3418 100644 --- a/xen/test/livepatch/Makefile +++ b/xen/test/livepatch/Makefile @@ -24,6 +24,9 @@ LIVEPATCH_PREPOST_HOOKS := xen_prepost_hooks.livepatch LIVEPATCH_PREPOST_HOOKS_FAIL := xen_prepost_hooks_fail.livepatch LIVEPATCH_ACTION_HOOKS := xen_action_hooks.livepatch LIVEPATCH_ACTION_HOOKS_NOFUNC := xen_action_hooks_nofunc.livepatch +LIVEPATCH_ACTION_HOOKS_MARKER:= xen_action_hooks_marker.livepatch +LIVEPATCH_ACTION_HOOKS_NOAPPLY:= xen_action_hooks_noapply.livepatch +LIVEPATCH_ACTION_HOOKS_NOREVERT:= xen_action_hooks_norevert.livepatch LIVEPATCHES += $(LIVEPATCH) LIVEPATCHES += $(LIVEPATCH_BYE) @@ -34,6 +37,9 @@ LIVEPATCHES += $(LIVEPATCH_PREPOST_HOOKS) LIVEPATCHES += $(LIVEPATCH_PREPOST_HOOKS_FAIL) LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS) LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOFUNC) +LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_MARKER) +LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOAPPLY) +LIVEPATCHES += $(LIVEPATCH_ACTION_HOOKS_NOREVERT) LIVEPATCH_DEBUG_DIR ?= $(DEBUG_DIR)/xen-livepatch @@ -158,7 +164,26 @@ $(LIVEPATCH_ACTION_HOOKS): xen_action_hooks.o xen_hello_world_func.o note.o xen_ $(LIVEPATCH_ACTION_HOOKS_NOFUNC): xen_action_hooks_nofunc.o note.o xen_note.o $(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_ACTION_HOOKS_NOFUNC) $^ +xen_actions_hooks_marker.o: config.h + +.PHONY: $(LIVEPATCH_ACTION_HOOKS_MARKER) +$(LIVEPATCH_ACTION_HOOKS_MARKER): xen_action_hooks_marker.o xen_hello_world_func.o note.o xen_note.o + $(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_ACTION_HOOKS_MARKER) $^ + +xen_actions_hooks_noapply.o: config.h + +.PHONY: $(LIVEPATCH_ACTION_HOOKS_NOAPPLY) +$(LIVEPATCH_ACTION_HOOKS_NOAPPLY): xen_action_hooks_marker.o xen_hello_world_func.o note.o xen_note.o + $(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_ACTION_HOOKS_NOAPPLY) $^ + +xen_actions_hooks_norevert.o: config.h + +.PHONY: $(LIVEPATCH_ACTION_HOOKS_NOREVERT) +$(LIVEPATCH_ACTION_HOOKS_NOREVERT): xen_action_hooks_marker.o xen_hello_world_func.o note.o xen_note.o + $(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_ACTION_HOOKS_NOREVERT) $^ + .PHONY: livepatch livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE) $(LIVEPATCH_NOP) $(LIVEPATCH_NO_XEN_BUILDID) \ $(LIVEPATCH_PREPOST_HOOKS) $(LIVEPATCH_PREPOST_HOOKS_FAIL) $(LIVEPATCH_ACTION_HOOKS) \ - $(LIVEPATCH_ACTION_HOOKS_NOFUNC) + $(LIVEPATCH_ACTION_HOOKS_NOFUNC) $(LIVEPATCH_ACTION_HOOKS_MARKER) $(LIVEPATCH_ACTION_HOOKS_NOAPPLY) \ + $(LIVEPATCH_ACTION_HOOKS_NOREVERT) diff --git a/xen/test/livepatch/xen_action_hooks.c b/xen/test/livepatch/xen_action_hooks.c index a947afc41f..39b5313027 100644 --- a/xen/test/livepatch/xen_action_hooks.c +++ b/xen/test/livepatch/xen_action_hooks.c @@ -28,6 +28,7 @@ static int apply_hook(livepatch_payload_t *payload) { struct livepatch_func *func = &payload->funcs[i]; + func->applied = LIVEPATCH_FUNC_APPLIED; apply_cnt++; printk(KERN_DEBUG "%s: applying: %s\n", __func__, func->name); @@ -48,6 +49,7 @@ static int revert_hook(livepatch_payload_t *payload) { struct livepatch_func *func = &payload->funcs[i]; + func->applied = LIVEPATCH_FUNC_NOT_APPLIED; revert_cnt++; printk(KERN_DEBUG "%s: reverting: %s\n", __func__, func->name); diff --git a/xen/test/livepatch/xen_action_hooks_marker.c b/xen/test/livepatch/xen_action_hooks_marker.c new file mode 100644 index 0000000000..4f807a577f --- /dev/null +++ b/xen/test/livepatch/xen_action_hooks_marker.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2019 Amazon.com, Inc. or its affiliates. All rights reserved. + * + */ + +#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 const char hello_world_patch_this_fnc[] = "xen_extra_version"; +extern const char *xen_hello_world(void); + +static int pre_apply_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED); + printk(KERN_DEBUG "%s: pre applied: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); + + return 0; +} + +static void post_apply_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + BUG_ON(func->applied != LIVEPATCH_FUNC_APPLIED); + printk(KERN_DEBUG "%s: post applied: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); +} + +static int pre_revert_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + BUG_ON(func->applied != LIVEPATCH_FUNC_APPLIED); + printk(KERN_DEBUG "%s: pre reverted: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); + + return 0; +} + +static void post_revert_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED); + printk(KERN_DEBUG "%s: post reverted: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); +} + +LIVEPATCH_PREAPPLY_HOOK(pre_apply_hook); +LIVEPATCH_POSTAPPLY_HOOK(post_apply_hook); +LIVEPATCH_PREREVERT_HOOK(pre_revert_hook); +LIVEPATCH_POSTREVERT_HOOK(post_revert_hook); + +struct livepatch_func __section(".livepatch.funcs") livepatch_xen_hello_world = { + .version = LIVEPATCH_PAYLOAD_VERSION, + .name = hello_world_patch_this_fnc, + .new_addr = xen_hello_world, + .old_addr = xen_extra_version, + .new_size = NEW_CODE_SZ, + .old_size = OLD_CODE_SZ, +}; + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/test/livepatch/xen_action_hooks_noapply.c b/xen/test/livepatch/xen_action_hooks_noapply.c new file mode 100644 index 0000000000..4c55c156a6 --- /dev/null +++ b/xen/test/livepatch/xen_action_hooks_noapply.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2019 Amazon.com, Inc. or its affiliates. All rights reserved. + * + */ + +#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 const char hello_world_patch_this_fnc[] = "xen_extra_version"; +extern const char *xen_hello_world(void); + +static unsigned int apply_cnt; + +static int pre_apply_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED); + printk(KERN_DEBUG "%s: pre applied: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); + + return 0; +} + +static int apply_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + apply_cnt++; + printk(KERN_DEBUG "%s: applying: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); + + return -EINVAL; /* Mark action as inconsistent */ +} + +static void post_apply_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + BUG_ON(apply_cnt != 1); + BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED); + printk(KERN_DEBUG "%s: post applied: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); +} + +static int pre_revert_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED); + printk(KERN_DEBUG "%s: pre reverted: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); + + return 0; +} + +static void post_revert_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED); + printk(KERN_DEBUG "%s: post reverted: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); +} + +LIVEPATCH_APPLY_HOOK(apply_hook); + +LIVEPATCH_PREAPPLY_HOOK(pre_apply_hook); +LIVEPATCH_POSTAPPLY_HOOK(post_apply_hook); +LIVEPATCH_PREREVERT_HOOK(pre_revert_hook); +LIVEPATCH_POSTREVERT_HOOK(post_revert_hook); + +struct livepatch_func __section(".livepatch.funcs") livepatch_xen_hello_world = { + .version = LIVEPATCH_PAYLOAD_VERSION, + .name = hello_world_patch_this_fnc, + .new_addr = xen_hello_world, + .old_addr = xen_extra_version, + .new_size = NEW_CODE_SZ, + .old_size = OLD_CODE_SZ, +}; + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/test/livepatch/xen_action_hooks_norevert.c b/xen/test/livepatch/xen_action_hooks_norevert.c new file mode 100644 index 0000000000..4408166f47 --- /dev/null +++ b/xen/test/livepatch/xen_action_hooks_norevert.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2019 Amazon.com, Inc. or its affiliates. All rights reserved. + * + */ + +#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 const char hello_world_patch_this_fnc[] = "xen_extra_version"; +extern const char *xen_hello_world(void); + +static unsigned int revert_cnt; + +static int pre_apply_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED); + printk(KERN_DEBUG "%s: pre applied: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); + + return 0; +} + +static void post_apply_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + BUG_ON(func->applied != LIVEPATCH_FUNC_APPLIED); + printk(KERN_DEBUG "%s: post applied: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); +} + +static int pre_revert_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + BUG_ON(func->applied != LIVEPATCH_FUNC_APPLIED); + printk(KERN_DEBUG "%s: pre reverted: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); + + return 0; +} + +static int revert_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + revert_cnt++; + printk(KERN_DEBUG "%s: reverting: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); + + return -EINVAL; /* Mark action as inconsistent */ +} + +static void post_revert_hook(livepatch_payload_t *payload) +{ + int i; + + printk(KERN_DEBUG "%s: Hook starting.\n", __func__); + + for (i = 0; i < payload->nfuncs; i++) + { + struct livepatch_func *func = &payload->funcs[i]; + + BUG_ON(revert_cnt != 1); + BUG_ON(func->applied != LIVEPATCH_FUNC_APPLIED); + + /* Outside of quiesce zone: MAY TRIGGER HOST CRASH/UNDEFINED BEHAVIOR */ + arch_livepatch_quiesce(); + arch_livepatch_revert(payload); + arch_livepatch_revive(); + BUG_ON(func->applied == LIVEPATCH_FUNC_APPLIED); + + printk(KERN_DEBUG "%s: post reverted: %s\n", __func__, func->name); + } + + printk(KERN_DEBUG "%s: Hook done.\n", __func__); +} + +LIVEPATCH_APPLY_HOOK(revert_hook); + +LIVEPATCH_PREAPPLY_HOOK(pre_apply_hook); +LIVEPATCH_POSTAPPLY_HOOK(post_apply_hook); +LIVEPATCH_PREREVERT_HOOK(pre_revert_hook); +LIVEPATCH_POSTREVERT_HOOK(post_revert_hook); + +struct livepatch_func __section(".livepatch.funcs") livepatch_xen_hello_world = { + .version = LIVEPATCH_PAYLOAD_VERSION, + .name = hello_world_patch_this_fnc, + .new_addr = xen_hello_world, + .old_addr = xen_extra_version, + .new_size = NEW_CODE_SZ, + .old_size = OLD_CODE_SZ, +}; + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ -- 2.16.5 Amazon Development Center Germany GmbH Krausenstr. 38 10117 Berlin Geschaeftsfuehrung: Christian Schlaeger, Ralf Herbrich Eingetragen am Amtsgericht Charlottenburg unter HRB 149173 B Sitz: Berlin Ust-ID: DE 289 237 879 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |